【Luogu】P2824排序(二分答案+线段树排序)
震惊!两个线段树和一个线段树竟是50分的差距!
本题可以使用二分答案,二分那个位置上最后是什么数。怎么验证呢?
把原序列改变,大于等于mid的全部变成1,小于mid的全部变成0,之后线段树排序。
最后看那个位置上是1还是0,若是1则说明最后那个位置上是个>=mid的数。
#include<cstdio> #include<cctype> #include<algorithm> #include<cstring> #include<cstdlib> #define left (rt<<1) #define right (rt<<1|1) #define mid ((l+r)>>1) #define lson l,mid,left #define rson mid+1,r,right #define maxn 300030 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } struct Que{ int opt,from,to; }q[maxn]; int d[maxn],w[maxn]; int tree[maxn*4],mem[maxn*4],tag[maxn*4]; inline void pushup(int rt){ tree[rt]=tree[left]+tree[right]; } inline void build(int l,int r,int rt){ tree[rt]=mem[rt]=tag[rt]=0; if(l==r){ tree[rt]=w[l]; //printf("%d %d\n",l,w[l]); return; } build(lson); build(rson); pushup(rt); } inline void pushdown(int rt,int m){ if(mem[rt]==0&&tag[rt]==0) return; if(mem[rt]){ mem[left]=mem[right]=1; tree[left]=tree[right]=0; tag[left]=tag[right]=0; mem[rt]=0; } if(tag[rt]){ tag[left]+=tag[rt]; tag[right]+=tag[rt]; tree[left]+=m-(m>>1); tree[right]+=m>>1; tag[rt]=0; } return; } void update(int from,int to,int l,int r,int rt){ if(from<=l&&to>=r){ tag[rt]++; tree[rt]+=r-l+1; return; } pushdown(rt,r-l+1); if(from<=mid) update(from,to,lson); if(to>mid) update(from,to,rson); pushup(rt); } void memdate(int from,int to,int l,int r,int rt){ if(from<=l&&to>=r){ tag[rt]=0; mem[rt]=1; tree[rt]=0; return; } pushdown(rt,r-l+1); if(from<=mid) memdate(from,to,lson); if(to>mid) memdate(from,to,rson); pushup(rt); } int query(int from,int to,int l,int r,int rt){ if(from<=l&&to>=r) return tree[rt]; pushdown(rt,r-l+1); int ans=0; if(from<=mid) ans+=query(from,to,lson); if(to>mid) ans+=query(from,to,rson); return ans; } bool check(int lim,int n,int m,int last){ build(1,n,1); for(int i=1;i<=m;++i){ int opt=q[i].opt,from=q[i].from,to=q[i].to; int c1=query(from,to,1,n,1); int c2=to-from+1-c1; //printf("%d %d<<\n",c1,c2); memdate(from,to,1,n,1); if(opt==0) update(from+c2,to,1,n,1); else update(from,from+c1-1,1,n,1); } //printf("zero\n"); //for(int i=1;i<=n;++i) printf("%d ",zero.query(i,i,1,n,1)); //printf("\none\n"); //for(int i=1;i<=n;++i) printf("%d ",one.query(i,i,1,n,1)); //printf("\n"); return query(last,last,1,n,1); } int main(){ int n=read(),m=read(); for(int i=1;i<=n;++i) d[i]=read(); for(int i=1;i<=m;++i) q[i]=(Que){read(),read(),read()}; int last=read(); int l=1,r=n,ans=0; while(l<=r){ //printf("%d %d %d\n",l,r,mid); for(int i=1;i<=n;++i) if(d[i]>=mid) w[i]=1; else w[i]=0; //for(int i=1;i<=n;++i) printf("%d<",w[i]); //printf("\n"); if(check(mid,n,m,last)){ ans=mid; l=mid+1; } else r=mid-1; } printf("%d",ans); return 0; }