bzoj 2653 middle (主席树+二分)

版权声明:本文为博主原创文章,未经博主允许不得转载。

bzoj 2653

题意:

  一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。

  给你一个长度为n的序列s。

  回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。

  其中a<b<c<d。

  位置也从0开始标号。

  强制在线。

解法:

  首先可以想到的是二分答案,再判断是否满足条件 。

  对于答案x,我们将原数组中大于等于x的数记1,小于的记为-1,那么一个区间是否满足中位数大于等于x的条件就是区间和大于等于0 。

  求解子段用线段树就可以快速做到,跟网上的主流做法不同,我线段树节点记录的是区间最大最小前缀和,查询的话只需询问区间[c,d]的最大前缀和 和 [a-1,b-1]的最小前缀和,两者一减就是最大的区间和,再判断它是否大于等于0 。这样子好写,而且效率更高 。(虽然不知道为什么,估计是优化到常数上了,当时是跑了940MS,排到了十三名,之前都没一题排这么前过 。。。)

  当然不可能对每一个答案x都建立一颗线段树,这时就要用到主席树,按不同的答案x建树 。之后随意搞搞就可以了 _(:з」∠)_

  

code

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <queue>
  7 #include <set>
  8 #include <vector>
  9 #include <map>
 10 #define LL long long
 11
 12 using namespace std;
 13
 14 const int N=20000+7;
 15
 16 int Ls[N*30],Rs[N*30],dc[N*30],mm[N*30][2]; // 0 最小值  1 最大值
 17 int root[N],tot=0;
 18
 19 struct node{
 20     int id,key;
 21     bool operator < (const node &t) const {
 22         return key<t.key;
 23     }
 24 }a[N];
 25 int sorted[N];
 26 int n;
 27
 28 inline bool scan_d(int &num)  {
 29     char in;bool IsN=false;
 30     in=getchar();
 31     if(in==EOF) return false;
 32     while(in!=‘-‘&&(in<‘0‘||in>‘9‘)) in=getchar();
 33     if(in==‘-‘){ IsN=true;num=0;}
 34     else num=in-‘0‘;
 35     while(in=getchar(),in>=‘0‘&&in<=‘9‘){
 36         num*=10,num+=in-‘0‘;
 37     }
 38     if(IsN) num=-num;
 39     return true;
 40 }
 41
 42 inline void pushup(int k){
 43     mm[k][0]=min(mm[Ls[k]][0],mm[Rs[k]][0])-dc[k];
 44     mm[k][1]=max(mm[Ls[k]][1],mm[Rs[k]][1])-dc[k];
 45 }
 46
 47 inline int bulidtree(int L,int R){
 48     int k=tot++;
 49     dc[k]=0;
 50
 51     if (L==R){
 52         mm[k][0]=mm[k][1]=L;
 53         return k;
 54     }
 55
 56     int mid=(L+R)>>1;
 57     Ls[k]=bulidtree(L,mid);
 58     Rs[k]=bulidtree(mid+1,R);
 59     pushup(k);
 60
 61     return k;
 62 }
 63
 64 inline void COPY(int x,int y){
 65     dc[x]=dc[y];
 66     mm[x][0]=mm[y][0];
 67     mm[x][1]=mm[y][1];
 68     Ls[x]=Ls[y];
 69     Rs[x]=Rs[y];
 70 }
 71
 72 inline int update(int o,int x,int y,int L,int R){
 73     int k=tot++;
 74     COPY(k,o);
 75     if (x==L && y==R){
 76         dc[k]+=2;
 77         mm[k][0]-=2;
 78         mm[k][1]-=2;
 79         return k;
 80     }
 81
 82     int mid=(L+R)>>1;
 83     if (y<=mid) Ls[k]=update(Ls[k],x,y,L,mid);
 84     else if (x>mid) Rs[k]=update(Rs[k],x,y,mid+1,R);
 85     else {
 86         Ls[k]=update(Ls[k],x,mid,L,mid);
 87         Rs[k]=update(Rs[k],mid+1,y,mid+1,R);
 88     }
 89     pushup(k);
 90
 91     return k;
 92 }
 93
 94 inline int query(int o,int x,int y,int L,int R,int op){
 95     if (L==x && R==y) return mm[o][op];
 96
 97     int mid=(L+R)>>1;
 98     if (y<=mid) return query(Ls[o],x,y,L,mid,op)-dc[o];
 99     else if (x>mid) return query(Rs[o],x,y,mid+1,R,op)-dc[o];
100     else {
101         if (op==1) return max(query(Ls[o],x,mid,L,mid,op),query(Rs[o],mid+1,y,mid+1,R,op))-dc[o];
102         else return min(query(Ls[o],x,mid,L,mid,op),query(Rs[o],mid+1,y,mid+1,R,op))-dc[o];
103     }
104 }
105
106 inline bool ok(int x,int a,int b,int c,int d){
107     return query(root[x],c,d,0,n,1)-query(root[x],a-1,b-1,0,n,0)>=0;
108 }
109
110 inline int search(int a,int b,int c,int d){
111     int L=1,R=n;
112     int mid;
113     while (L<=R){
114         mid=(L+R)>>1;
115         if (ok(mid,a,b,c,d)) L=mid+1;
116         else R=mid-1;
117     }
118     return sorted[R];
119 }
120
121 int main(){
122     scan_d(n);
123     for (int i=1;i<=n;i++){
124         scan_d(a[i].key);
125         sorted[i]=a[i].key;
126         a[i].id=i;
127     }
128     sort(sorted+1,sorted+n+1);
129     sort(a+1,a+n+1);
130
131     root[0]=bulidtree(0,n);
132     int j=1;
133     for (int i=1;i<=n;i++){
134         root[i]=root[i-1];
135         while (j<=n && a[j].key<sorted[i]){
136             root[i]=update(root[i],a[j].id,n,0,n);
137             j++;
138         }
139     }
140
141     int m,q[4],ans=0;
142     scan_d(m);
143     while (m--){
144         for (int i=0;i<4;i++){
145             scan_d(q[i]);
146             q[i]=(q[i]%n+ans%n)%n+1;
147         }
148         sort(q,q+4);
149         printf("%d\n",ans=search(q[0],q[1],q[2],q[3]));
150     }
151     return 0;
152 }
时间: 2024-10-12 13:11:19

bzoj 2653 middle (主席树+二分)的相关文章

BZOJ 2653: middle [主席树 中位数]

传送门 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 我会使用一些方式强制你在线. 最后一句话太可怕了$QAQ$ 首先需要知道怎么求中位数: 二分答案,$\ge$的为$1$,$<$的为$-1$,如果和$\ge 0$说明当前答案$\le$中位数 最大中位数?$GSS$! 只要求$[a,b].rm+(b,c)

BZOJ 2653 middle | 主席树

题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前ans是大了还是小了 然后二分答案,就是求最大子段和的问题,根据网上的题解:[b,c]是必选的,然后选[a,b]和[c,d]的最大字段和就行了 #include<cstdio> #include<cstring> #include<algorithm> #define N 20

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意: 给你n个数,有m次询问 每次问你在区间[l,r]内 第k小的|\(a_i-p\)|是多少 题解: 主席树+二分 每次二分答案 如果p+mid到p-mid的值的个数大于k个的话,mid值就是可行了,然后缩小区间往左找即可 因为保证有解,所以二分出来的mid值就是答案了 que

Luogu2839 Middle 主席树、二分答案

题目传送门:https://www.luogu.org/problemnew/show/P2839 题目大意:给出一个长度为$N$的序列与$Q$次询问,每次询问左端点在$[a,b]$,右端点在$[c,d]$的区间中最大的中位数,强制在线(本题中的中位数定义与平常不同,设某区间长度为$L$,则在从小到大排序后的序列中(编号从$0$开始),其中位数为第$\lfloor L/2 \rfloor$号元素)$N,Q \leq 2 \times 10^4$ 这鬼题让我知道主席树可以用于除第$K$大以外的问题

BZOJ 2653: middle

2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1536  Solved: 855[Submit][Status][Discuss] Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 其中a<b<c<d. 位置

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

BZOJ1926 [Sdoi2010]粟粟的书架 【主席树 + 二分 + 前缀和】

题目 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都摆有一本书,上数第i 行.左数第j 列 摆放的书有Pi,j页厚.粟粟每天除了读书之外,还有一件必不可少的工作就是摘苹果,她每天必须摘取一个指定的 苹果.粟粟家果树上的苹果有的高.有的低,但无论如何凭粟粟自己的个头都难以摘到.不过她发现, 如果在脚 下放上几本书,就可以够着苹果:她同时注意到,对于第

HDU - 6621 K-th Closest Distance 主席树+二分答案

K-th Closest Distance 主席树第二波~ 题意 给你\(n\)个数\(m\)个询问,问\(i\in [l,r]\)计算每一个\(|a_{i}-p|\)求出第\(k\)小 题目要求强制在线\(l = l \oplus ans.r = r \oplus ans.p = p \oplus ans.k = k \oplus ans\)(ans为上次询问的答案) 思路 二分答案\(ans\),找区间\(i\in[l,r], a_{i} \in [p-ans, p+ans]\)里的数量\(

BZOJ 2735: 世博会 主席树+切比雪夫距离转曼哈顿距离

2735: 世博会 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 124  Solved: 51[Submit][Status][Discuss] Description 四年一度的世博会又要举办了,Q国很荣幸成为了这次世博会的主办方.Q国主席QQ从全国各地收集了N件物品排成 一排,作为Q国馆的展出物.对于相邻摆放的一些物品,如果过于相似会让人觉得无聊,如果差别过大又会让人觉 得突兀.为了让人们对这次世博会的展出满意,QQ需要知道一些相邻物品的“