来自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 ",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; }