AtCoder Beginner Contest 237 G - Range Sort Query
阿新 • • 發佈:2022-02-10
題目大意
一個1~n的排列,進行m次區間升/降序排序操作,問x最終所在的位置。
思路
這道題不復雜,但不好想,還容易想到一些沒用的方法(如平衡樹)。
我們嘗試換個思路,我們要找的這個位置的值滿足>=x且不滿足>=x+1。
這看起來是廢話(與=x完全等價),但是可以拆分上面兩個限制條件,將排列變為兩個只含0/1的序列,最終滿足一個為0一個為1的位置就是答案。
這樣,區間排序就很容易了,我們只在乎0/1,不在乎取值,0和1各自放一起,直接用線段樹維護就好。
具體來說,查詢區間內0/1個數,前面放0/1,後面放1/0,即為排序。
#include<bits/stdc++.h> #define mid ((l+r)>>1) #define inf 1000000007 using namespace std; int n,m,T,pos; struct node { int t[1000005][2],tag[1000005]; void build(int l,int r,int k) { t[k][0]=r-l+1; if(l==r)return; build(l,mid,k*2); build(mid+1,r,k*2+1); } void pushdown(int l,int r,int k) { int v=tag[k]; if(!v)return; tag[k*2]=tag[k*2+1]=v; v--; t[k*2][v]=mid-l+1,t[k*2][v^1]=0; t[k*2+1][v]=r-mid,t[k*2+1][v^1]=0; tag[k]=0; } void fix(int l,int r,int k,int x,int y,int v) { if(x>y)return; if(l<r)pushdown(l,r,k); if(l==x&&r==y) { t[k][v]=r-l+1,t[k][v^1]=0; if(l<r)tag[k]=v+1; return; } if(y<=mid)fix(l,mid,k*2,x,y,v); else if(x>mid)fix(mid+1,r,k*2+1,x,y,v); else fix(l,mid,k*2,x,mid,v),fix(mid+1,r,k*2+1,mid+1,y,v); t[k][0]=t[k*2][0]+t[k*2+1][0]; t[k][1]=t[k*2][1]+t[k*2+1][1]; } int find(int l,int r,int k,int x,int y,int v) { if(l<r)pushdown(l,r,k); if(l==x&&r==y) { return t[k][v]; } if(y<=mid)return find(l,mid,k*2,x,y,v); else if(x>mid)return find(mid+1,r,k*2+1,x,y,v); else return find(l,mid,k*2,x,mid,v)+find(mid+1,r,k*2+1,mid+1,y,v); t[k][0]=t[k*2][0]+t[k*2+1][0]; t[k][1]=t[k*2][1]+t[k*2+1][1]; } void rev(int l,int r,int k) { int mad=find(1,n,1,l,r,k); fix(1,n,1,l,l+mad-1,k); fix(1,n,1,l+mad,r,k^1); } }ta,tb; long long read() { long long x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x*f; } void calc(int l,int r,int k) { if(l==r) { if(ta.t[k][0]^tb.t[k][0]) { pos=l; } return; } ta.pushdown(l,r,k); tb.pushdown(l,r,k); calc(l,mid,k*2); calc(mid+1,r,k*2+1); } int main() { n=read(),m=read(),T=read(); ta.build(1,n,1); tb.build(1,n,1); for(int i=1,x;i<=n;i++) { x=read(); if(x>=T) { ta.fix(1,n,1,i,i,1); } if(x>=T+1) { tb.fix(1,n,1,i,i,1); } } for(int i=1,opt,l,r;i<=m;i++) { opt=read(),l=read(),r=read(); ta.rev(l,r,opt-1); tb.rev(l,r,opt-1); } calc(1,n,1); printf("%d\n",pos); return 0; }