【UOJ UNR #1】火车管理

来自FallDream的博客,未经允许,请勿转载,谢谢。


题面

 

考虑用可持久化线段树直接维护每个点在不同时刻,第一辆车的编号。

这样3操作就变成了区间赋值,1操作变成区间和

2操作的话,只需要查询一下现在这辆车的编号,再到历史版本去查一下上一辆车的编号就行了。

#include<iostream>
#include<cstdio>
#define MN 500000
using namespace std;
inline int read()
{
    int 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*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,ty,rt[MN+5],cnt=0,num[MN+5];
struct Tree{
    int l,r,sum,val;
}T[MN*131];
inline int newnode(int x,int flag=0){if(flag)return x;T[++cnt]=T[x];return cnt;}
inline void Mark(int x,int len,int v){T[x].val=v;T[x].sum=len*num[v];}
inline void pushdown(int x,int lt,int rt)
{
    int mid=lt+rt>>1;
    Mark(T[x].l=newnode(T[x].l),mid-lt+1,T[x].val);Mark(T[x].r=newnode(T[x].r),rt-mid,T[x].val);T[x].val=0;
}

int Build(int l,int r)
{
    int x=++cnt;
    if(l!=r) T[x].l=Build(l,l+r>>1),T[x].r=Build((l+r>>1)+1,r);
    return x; 
}

int Query(int x,int l,int r,int lt,int rt)
{
    if(l==lt&&r==rt) return T[x].sum;int mid=lt+rt>>1;
    if(T[x].val) pushdown(x,lt,rt);
    if(r<=mid) return Query(T[x].l,l,r,lt,mid);
    else if(l>mid) return Query(T[x].r,l,r,mid+1,rt);
    else return Query(T[x].l,l,mid,lt,mid)+Query(T[x].r,mid+1,r,mid+1,rt);
}

int Query(int x,int k,int lt,int rt)
{
    if(lt==rt) return T[x].val;int mid=lt+rt>>1;
    if(T[x].val) pushdown(x,lt,rt);
    if(k>mid) return Query(T[x].r,k,mid+1,rt);
    else return Query(T[x].l,k,lt,mid);
}

void Modify(int x,int l,int r,int lt,int rt,int v)
{
    if(l==lt&&r==rt) {Mark(x,rt-lt+1,v);return;}    
    int mid=lt+rt>>1,flag=T[x].val;
    if(T[x].val) pushdown(x,lt,rt);
    if(r<=mid) Modify(T[x].l=newnode(T[x].l,flag),l,r,lt,mid,v);
    else if(l>mid) Modify(T[x].r=newnode(T[x].r,flag),l,r,mid+1,rt,v);
    else Modify(T[x].l=newnode(T[x].l,flag),l,mid,lt,mid,v),
         Modify(T[x].r=newnode(T[x].r,flag),mid+1,r,mid+1,rt,v);
    T[x].sum=T[T[x].l].sum+T[T[x].r].sum;
}
int last=0;
int main()
{
    n=read();m=read();ty=read();rt[0]=Build(1,n);
    for(int i=1;i<=m;++i)
    {
        int op=read();rt[i]=newnode(rt[i-1]);
        if(op==1) {int l=(read()+last*ty)%n+1,r=(read()+last*ty)%n+1;printf("%d\n",last=Query(rt[i],min(l,r),max(l,r),1,n));}
        if(op==2) {int x=(read()+last*ty)%n+1,y=Query(rt[i],x,1,n);if(y!=0) Modify(rt[i],x,x,1,n,Query(rt[y-1],x,1,n));}
        if(op==3) {int l=(read()+last*ty)%n+1,r=(read()+last*ty)%n+1;num[i]=read();Modify(rt[i],min(l,r),max(l,r),1,n,i);}    
    }
    return 0;
}

 

posted @ 2017-09-01 16:55  FallDream  阅读(403)  评论(0编辑  收藏  举报