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);
    }
}

 

posted @ 2019-10-25 10:30  dzzx_Syh  阅读(109)  评论(0编辑  收藏  举报