题意:给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
强制在线。
思路:首先考虑二分答案,判断可行的方法则是看是否小于他的数可以比大于他的数多。则考虑对于[b+1, c-1]直接求出来,对于[a, b]求最大的小的减大的后缀,[c, d]求最大前缀,可以建线段树维护。对于每一个数建一个线段树,则空间爆了,考虑使用主席树维护
那么对于第i颗主席树,则是小于 i 的都是-1,大于等于 i 的是1,查询的时候二分答案查询在排名 i 的这颗树上查是否能选出序列使得和大于等于0
https://www.luogu.org/problemnew/show/P2839

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define MAXN 20050
using namespace std;
inline int read(){int f = 1, ret = 0; char ch = getchar();while(ch < '0' || ch > '9') if(ch == '-') f = -1, ch = getchar();while(ch >= '0' && ch <= '9') ret = ret*10+int(ch-'0'), ch = getchar();return ret*f;
}
void print(int x){if(x < 10) putchar(x+'0');else{print(x/10);putchar(x%10+'0');}
}
int n, cnt, Q, lastans, q[4], root[MAXN];
struct node1{int id, num;bool operator < (const node1 &x) const{return num < x.num;}node1(){}node1(int _id, int _num){id = _id, num = _num;}
}a[MAXN<<2];
struct data{int lmax, rmax, tot;
};
struct node{int ls, rs;data d;
}t[MAXN<<6];
data merge(data a, data b){data ret;ret.tot = a.tot + b.tot;ret.lmax = max(a.lmax, a.tot + b.lmax);ret.rmax = max(b.rmax, b.tot + a.rmax);return ret;
}
void build(int &u, int l, int r){int tmp = u; u = ++cnt; t[u] = t[tmp];if(l == r) {t[u].d.tot = t[u].d.lmax = t[u].d.rmax = 1; return;}int mid = (l+r)>>1;build(t[u].ls, l, mid);build(t[u].rs, mid+1, r);t[u].d = merge(t[t[u].ls].d, t[t[u].rs].d);
}
void update(int &u, int l, int r, int x){int tmp = u; u = ++cnt; t[u] = t[tmp];if(l == r){t[u].d.tot = t[u].d.lmax = t[u].d.rmax = -1; return;}int mid = (l+r)>>1;if(x <= mid) update(t[u].ls, l, mid, x);else update(t[u].rs, mid+1, r, x);t[u].d = merge(t[t[u].ls].d, t[t[u].rs].d);
}
data query(int u, int l, int r, int tl, int tr){if(tl <= l && r <= tr) return t[u].d;int mid = (l+r)>>1;if(tr <= mid) return query(t[u].ls, l, mid, tl, tr);if(mid < tl) return query(t[u].rs, mid+1, r, tl, tr);else return merge(query(t[u].ls, l, mid, tl, tr), query(t[u].rs, mid+1, r, tl, tr));
}
bool check(int id, int l1, int r1, int l2, int r2){int ret = 0;if(r1+1 <= l2-1) ret += query(root[id], 1, n, r1+1, l2-1).tot;ret += query(root[id], 1, n, l1, r1).rmax;ret += query(root[id], 1, n, l2, r2).lmax;//printf("%d %d\n", id, ret);return ret>=0;
}
/*
输入格式:
第一行序列长度n。
接下来n行按顺序给出a中的数。
接下来一行Q
然后Q行每行a,b,c,d,我们令上个询问的答案是x(如果这是第一个询问则x=0)。
令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。将q从小到大排序之后,令真正的要询问的a=q[0],b=q[1],c=q[2],d=q[3]。
n<=20000,Q<=25000*/
int main(){//freopen("1.in", "r", stdin);//freopen("1.out", "w", stdout);scanf("%d", &n);//n = read();for(int i = 1; i <= n; i++){scanf("%d", &a[i].num); a[i].id = i;//a[i] = node1(i, read());}sort(a+1, a+n+1);build(root[1], 1, n);for(int i = 2; i <= n; i++) root[i] = root[i-1], update(root[i], 1, n, a[i-1].id);scanf("%d", &Q);//Q = read();while(Q--){for(int i = 0; i < 4; i++) scanf("%d", &q[i]), q[i] = (q[i]+lastans)%n;//q[i] = (read()+lastans)%n;sort(q, q+4); for(int i = 0; i < 4; i++) q[i]++;int l = 1, r = n, mid, ans;while(l <= r){mid = (l+r)>>1;if(check(mid, q[0], q[1], q[2], q[3])) ans = mid, l = mid+1;else r = mid-1;}printf("%d\n", lastans = a[ans].num);//print(lastans = a[ans].num); putchar('\n'); }return 0;
}

【国家集训队】middle相关推荐

  1. P2839 [国家集训队]middle(二分 套 主席树)

    P2839 [国家集训队]middle 有一个长度为nnn的序列,有mmm次询问,每次询问a,b,c,da, b, c, da,b,c,d,为l∈[a,b],r∈[c,d]l \in [a, b], ...

  2. 洛谷P2839 [国家集训队]middle(主席树)

    P2839 [国家集训队]middle 我们可以考虑二分中位数 checkcheckcheck 答案,那么我们对于某个值 midmidmid ,把 [l,r][l,r][l,r] 内的所有小于 mid ...

  3. bzoj 2653 洛谷 P2839 [国家集训队] middle

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2381  Solved: 1340 [Submit][Status][Di ...

  4. 可持久化普通线段树 ---- P2839 [国家集训队]middle 可持久化普通线段树 + 二分 求中位数最大值

    题目链接 题目大意: 解题思路: 这个题思路很妙!! 首先我们假设只有一次询问怎么做? 那么我们可以二分出这个最大值midmidmid,然后把大于等于midmidmid设置成111,把小于midmid ...

  5. luogu2839 [国家集训队]middle

    题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...

  6. [bzoj 2653][国家集训队]middle

    传送门 Description 一个长度为\(n\)的序列\(a\),设其排过序之后为\(b\),其中位数定义为\(b[n/2]\),其中\(a,b\)从\(0\)开始标号,除法取下整. 给你一个长度 ...

  7. P2839 [国家集训队]middle

    题面 • 提一下静态区间第k小的nlog2n的做法: 1. 建关于排名的主席树(按排名顺序建树). 2. 二分答案. • 这样做静态区间第k小的虽然有些ZZ,但它的意义在于将线段树   维护的对象改变 ...

  8. P2839 [国家集训队]middle 二分 + 主席树 在值域上建区间

    传送门 文章目录 题意: 思路: 题意: 思路: 我们先解决怎么判断中位数的问题,我们可以二分一个midmidmid,将<mid<mid<mid的值都变成−1-1−1,其他的数都变成 ...

  9. [国家集训队]middle(二分+主席树[中位数思维题])

    文章目录 点击查看 solution code 点击查看 solution 简单口胡一下就跑 考虑二分答案ansansans 区间[x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1 ...

  10. [国家集训队]middle

    嘟嘟嘟 有谁能想到这题会用到主席树呢?(不愧是WJMZBMR出的题) 首先考虑如果区间是固定的话,中位数该怎么求. 没错,二分.如果大于当前二分值\(mid\)的数比小于\(mid\)的数多,说明\( ...

最新文章

  1. 虚拟机 硬盘容量不够 增大的方法
  2. 湖南大学计算机考研考什么,2017年湖南大学计算机系统考研大纲
  3. Netty学习笔记(一)Netty客户端源码分析
  4. Struts文件上传与下载详解_文件的下载
  5. C语言 函数值传递和址传递 - C语言零基础入门教程
  6. IEnumerable
  7. Mutual Review
  8. 基于大数据技术推荐系统算法案例实战教程
  9. 51单片机c语言程序执行顺序,51单片机程序执行流程详解
  10. java怎么求传递闭包_利用定义求解传递闭包的关系矩阵
  11. JCMsuite 纳米光学仿真分析
  12. ai人工智能开发_面向开发人员的十大人工智能(AI)工具
  13. 女生专属树洞,树懒APP内测(附下载)
  14. 微软日语输入法用法说明
  15. PreScan 教程:0. PreScan与Matlab连接
  16. 不改HOST,另类打开谷歌搜索的方法
  17. 使用QT5书写的护眼程序
  18. 2.4gwifi最高下载速度_宽带200m,光猫和无线一体的猫,5g和2.4g无线下速度多少是正常?...
  19. 学习笔记 查分约束系统
  20. 用树莓派制作一款只有刷脸才能开的保险柜

热门文章

  1. one 主格 复数 宾格_主格、宾格、名词所有格
  2. 2021-11-12每日刷题打卡
  3. 双能CT的基本原理及理解笔记
  4. 卡通可爱的门户网站登录表单页面
  5. springboot定时器@Scheduled的cron,fixedRate,fixedDelay使用
  6. 开源项目管理软件排名_2014年排名前5位的开源项目管理工具
  7. 只需8步,轻松构建用户画像标签体系
  8. [Caffe]: HDF5Data Layer
  9. python注册登陆程序_python的简单的登陆和注册功能实现
  10. agv机器人无人仓系统-开源agv控制系统opentcs