您的位置:首页 > 其它

[BZOJ4552][Tjoi2016&Heoi2016][线段树][二分]排序

2017-02-13 20:01 537 查看

题意

求给定序列经过给定排序网络后的第k个元素

鏼爷16年论文小例题%%%

二分答案x,原数列中大于等于x的设为1,小于x的设为0。

每一次排序的区间[l,r]中,有k1个0,k2个1,那么升序就把前k1个覆盖为0,后k2个覆盖为1,降序相反。

可以用线段树维护。

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 100010

using namespace std;

int n,m,q;
int A
,B
;
struct stp{
int l,r,op;
}s
;
struct lisan{
int x,g;
friend bool operator <(lisan a,lisan b){return a.x<b.x;}
}L
;
struct sigt{
int l,r,z,o,flg;
}T[N<<2];

inline void reaD(int &x){
char Ch=getchar();x=0;
for(;Ch>'9'||Ch<'0';Ch=getchar());
for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=getchar());
}

inline void upd(int g){
T[g].z=T[g<<1].z+T[g<<1|1].z;
T[g].o=T[g<<1].o+T[g<<1|1].o;
}

inline void Set(int g,int w){
if(w==1) T[g].z=T[g].r-T[g].l+1,T[g].o=0;
else T[g].o=T[g].r-T[g].l+1,T[g].z=0;
T[g].flg=w;
}

inline void pushdown(int g){
if(!T[g].flg) return;
Set(g<<1,T[g].flg);
Set(g<<1|1,T[g].flg);
T[g].flg=0;
}

void build(int g,int l,int r){
T[g].l=l;T[g].r=r;T[g].flg=0;
if(l==r){
if(B[l]) T[g].o=1,T[g].z=0;
else T[g].o=0,T[g].z=1;
return ;
}
int mid=l+r>>1;
build(g<<1,l,mid);
build(g<<1|1,mid+1,r);
upd(g);
}

int query(int g,int l,int r,int w){
if(T[g].l==l&&T[g].r==r) return w==1?T[g].o:T[g].z;
pushdown(g);
int mid=T[g].l+T[g].r>>1;
if(r<=mid) return query(g<<1,l,r,w);
if(l>mid) return query(g<<1|1,l,r,w);
return query(g<<1,l,mid,w)+query(g<<1|1,mid+1,r,w);
}

void cover(int g,int l,int r,int w){
if(T[g].l==l&&T[g].r==r){Set(g,w);return;}
pushdown(g);
int mid=T[g].l+T[g].r>>1;
if(r<=mid) cover(g<<1,l,r,w);
else if(l>mid) cover(g<<1|1,l,r,w);
else cover(g<<1,l,mid,w),cover(g<<1|1,mid+1,r,w);
upd(g);
}

inline bool check(int x){
for(int i=1;i<=n;i++) B[i]=A[i]>=x;
build(1,1,n);
for(int i=1;i<=m;i++){
int z=query(1,s[i].l,s[i].r,0),o=s[i].r-s[i].l+1-z;
if(!z||!o) continue;
if(s[i].op) cover(1,s[i].l,s[i].l+o-1,2),cover(1,s[i].r-z+1,s[i].r,1);
else cover(1,s[i].r-o+1,s[i].r,2),cover(1,s[i].l,s[i].l+z-1,1);
}
return query(1,q,q,1);
}

int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
reaD(n); reaD(m);
for(int i=1;i<=n;i++) reaD(A[i]);
for(int i=1;i<=m;i++) reaD(s[i].op),reaD(s[i].l),reaD(s[i].r);
reaD(q); int l=1,r=n,mid,Ans;
while(l<=r) check(mid=l+r>>1)?Ans=mid,l=mid+1:r=mid-1;
return printf("%d\n",Ans),0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: