luogu P3960 列队
搞很多棵动态开点线段树维护区间第K大。。
wocao..
细节很多。。
啥也不说了。
Code
#include<iostream> #include<cstdio> #define N 300010 #define ll long long using namespace std; int n,m,q,root[N],tot,mx,now,last[N]; inline int read(){ char c=getchar();int x=0,flag=1; while(c<'0' || c>'9'){if(c=='-') flag=-1;c=getchar();} while(c>='0' && c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar(); return x*flag; } struct Segmenttree{ int lc,rc,sz;ll pos; }t[N*30]; int get(int l,int r){ if(now==n+1){ if(r<=n) return r-l+1; if(l<=n) return n-l+1; return 0; } if(r<m) return r-l+1; if(l<m) return m-l; return 0; } ll query(int &p,int l,int r,int k){ if(!p){ p=++tot; t[p].sz=get(l,r); if(l==r){ if(now==n+1) t[p].pos=1ll*l*m; else t[p].pos=1ll*(now-1)*m+l; } } t[p].sz--; if(l==r) return t[p].pos; int mid=(l+r)>>1; if((!t[p].lc && k<=mid-l+1) || (k<=t[t[p].lc].sz)) return query(t[p].lc,l,mid,k); else{ if(!t[p].lc) return query(t[p].rc,mid+1,r,k-(mid-l+1)); else return query(t[p].rc,mid+1,r,k-t[t[p].lc].sz); } } void update(int &p,int l,int r,int x,ll k){ if(!p){ p=++tot; t[p].sz=get(l,r); } t[p].sz++; if(l==r){t[p].pos=k;return;} int mid=(l+r)>>1; if(x<=mid) update(t[p].lc,l,mid,x,k); else update(t[p].rc,mid+1,r,x,k); } int main(){ n=read();m=read();q=read();mx=max(n,m)+q; while(q--){ int x=read(),y=read();ll ans; if(y==m) now=n+1,ans=query(root[n+1],1,mx,x); else now=x,ans=query(root[x],1,mx,y); printf("%lld\n",ans); now=n+1;update(root[n+1],1,mx,n+(++last[n+1]),ans); if(y!=m) ans=query(root[n+1],1,mx,x),now=x,update(root[x],1,mx,m-1+(++last[x]),ans); } }