uoj218_ train management

The meaning of problems

\ (n-\) positions, each position a stack, three operations, and interrogation interval stack, a stack segment number, a number of single points of the stack.

analysis

  • With a tree line to maintain the top of the stack and, interval (single point) and update interval of inquiry.
  • With a chairman for each tree to maintain the position of a stack of the latest time that the President of trees saved is time, then remove the time also Chairman of the tree as a subscript to access the corresponding time version .
  • Therefore, when the interval stack segment tree update interval and update interval chairman trees.
  • When a single point from the stack, first check the stack top element of time in this position, then use the previous version of this tree query time by the Chairman of the stack element at a time stack, the stack according to the time of the stack may know elements, and then because the top of the stack has been popped, so the new top of the stack is the element, single-point update segment tree and Chairman tree.

Code

#include <bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define mid (l+r)/2
using namespace std;
typedef long long ll;
const int N=8e5+50;
int n,m,ty,o,l1,r1,x[N];
struct ST{
    //lz:区间赋值标记 sum:区间和
    ll lz[N*4],sum[N*4];
    void pushup(int i){
        sum[i]=sum[ls]+sum[rs];
    }
    void pushdown(int i,int l,int r){
        if(lz[i]){
            lz[ls]=lz[i];
            lz[rs]=lz[i];
            sum[ls]=(mid-l+1)*lz[i];
            sum[rs]=(r-mid)*lz[i];
            lz[i]=0;
        }
    }
    void update(int i,int l,int r,int ql,int qr,int v){
        if(ql<=l && qr>=r){
            lz[i]=v;
            sum[i]=1ll*(r-l+1)*v;
            return;
        }
        pushdown(i,l,r);
        if(ql<=mid){
            update(ls,l,mid,ql,qr,v);
        }
        if(qr>mid){
            update(rs,mid+1,r,ql,qr,v);
        }
        pushup(i);
    }
    ll query(int i,int l,int r,int ql,int qr){
        if(ql<=l && qr>=r){
            return sum[i];
        }
        pushdown(i,l,r);
        ll ans=0;
        if(ql<=mid){
            ans+=query(ls,l,mid,ql,qr);
        }
        if(qr>mid){
            ans+=query(rs,mid+1,r,ql,qr);
        }
        return ans;
    }
}st;
int tr[N];
struct CT{
    int tot=0,tim[N*50],lr[N*50],rr[N*50];
    int update(int pre,int l,int r,int ql,int qr,int t){
        int rt=++tot;
        tim[rt]=t;
        lr[rt]=lr[pre];
        rr[rt]=rr[pre];
        if(ql<=l && qr>=r){
            lr[rt]=rr[rt]=(l==r?0:rt);
        }else{
            if(ql<=mid){
                lr[rt]=update(lr[pre],l,mid,ql,qr,t);
            }
            if(qr>mid){
                rr[rt]=update(rr[pre],mid+1,r,ql,qr,t);
            }
        }
        return rt;
    }
    int query(int i,int l,int r,int v){
        if(l==r && l==v){
            return tim[i];
        }
        if(v<=mid){
            return query(lr[i],l,mid,v);
        }else{
            return query(rr[i],mid+1,r,v);
        }
    }
}ct;
int dec(int l1,int lst){
    return (l1+lst*ty)%n+1;
}
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&m,&ty);
    ll lst=0;
    for(int t=1;t<=m;t++){
        scanf("%d",&o);
        tr[t]=tr[t-1];
        if(o==1){
            scanf("%d%d",&l1,&r1);
            l1=dec(l1,lst);
            r1=dec(r1,lst);
            int l=min(l1,r1);
            int r=max(l1,r1);
            //直接查询线段树区间和
            lst=st.query(1,1,n,l,r);
            printf("%lld\n",lst);
        }else if(o==2){
            scanf("%d",&l1);
            int l=dec(l1,lst);
            //查询l这个位置最新插入的时间
            int tm=ct.query(tr[t],1,n,l);
            //查询再前一个插入时间,即将最新插入出栈
            int pt=ct.query(tr[tm-1],1,n,l);
            //线段树单点修改为上一个版本
            st.update(1,1,n,l,l,x[pt]);
            //主席树对当前最新版本单点修改l位置的插入时间
            tr[t]=ct.update(tr[t],1,n,l,l,pt);
        }else if(o==3){
            scanf("%d%d%d",&l1,&r1,&x[t]);
            l1=dec(l1,lst);
            r1=dec(r1,lst);
            int l=min(l1,r1);
            int r=max(l1,r1);
            //线段树区间更新
            st.update(1,1,n,l,r,x[t]);
            //前面已经有tr[t]=tr[t-1] 无论更不更新都复制一个新版本
            //主席树区间更新
            tr[t]=ct.update(tr[t],1,n,l,r,t);
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zxcoder/p/11391024.html