[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; }
相关文章推荐
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树
- bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树
- [bzoj4552][Tjoi2016&Heoi2016]排序 二分+线段树
- [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树
- 【BZOJ4552】[Tjoi2016&Heoi2016]排序 二分+线段树
- 【BZOJ】4552 [Tjoi2016&Heoi2016]排序 二分+线段树
- bzoj4552 [Tjoi2016&Heoi2016]排序(二分答案+线段树)
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树)
- [BZOJ4552][Tjoi2016&Heoi2016]排序 二分+线段树
- [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树
- 【二分+线段树】BZOJ4552 [Tjoi2016&Heoi2016]排序
- BZOJ4552 [Tjoi2016&Heoi2016]排序 【二分 + 线段树】
- 【二分+线段树】BZOJ4552(Tjoi2016&Heoi2016)[排序]题解
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 [二分][线段树]
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案
- 【bzoj4552】[Tjoi2016&Heoi2016]排序 二分+线段树
- [BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 二分 线段树
- bzoj 4552: [Tjoi2016&Heoi2016]排序【二分+线段树】
- bzoj4552 [Tjoi2016&Heoi2016]排序 线段树+二分答案