很简单
用一个线段树维护
1.答案
2.当前栈顶是什么时候push进来的
然后用一棵以时间为版本的可持久化线段树维护每个操作之后第一个覆盖到他的操作是哪个
就可以了
询问直接在线段树上询问,修改在两棵树上分别修改即可
调一年
//wls niubi! #include<bits/stdc++.h> #define LL long long using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int maxn = 500010; int n,m,ty,rt; int tot; int dfn,root[maxn],ls[maxn << 7],rs[maxn << 7],val[maxn << 7],tag[maxn << 7],w[maxn]; inline void pushdown(int x,int l,int r) { if(l == r || !tag[x])return; int t = tag[x],mid = (l + r) >> 1;tag[x] = 0; if(!ls[x])ls[x] = ++dfn; if(!rs[x])rs[x] = ++dfn; tag[ls[x]] = tag[rs[x]] = t; val[ls[x]] = w[t] * (mid - l + 1); val[rs[x]] = w[t] * (r - mid); } inline int query(int x,int l,int r,int L,int R) { if(!x)return 0; pushdown(x,l,r); if(L <= l && r <= R)return val[x]; int mid = (l + r) >> 1,ans = 0; if(L <= mid)ans += query(ls[x],l,mid,L,R); if(R > mid)ans += query(rs[x],mid + 1,r,L,R); return ans;/* if(R <= mid)return query(ls[x],l,mid,L,R); else if(L > mid)return query(rs[x],mid + 1,r,L,R); else return query(ls[x],l,mid,L,R) + query(rs[x],mid + 1,r,L,R);*/ } inline int qid_1(int x,int l,int r,int p) { if(tag[x])return tag[x]; if(l == r)return tag[x]; int mid = (l + r) >> 1; if(p <= mid)return qid_1(ls[x],l,mid,p); else return qid_1(rs[x],mid + 1,r,p); } inline int qid_2(int x,int l,int r,int p) { pushdown(x,l,r); if(l == r)return tag[x]; int mid = (l + r) >> 1; if(p <= mid)return qid_2(ls[x],l,mid,p); else return qid_2(rs[x],mid + 1,r,p); } inline void modify(int &x,int l,int r,int L,int R,int va) { if(!x)x = ++dfn; pushdown(x,l,r); if(L <= l && r <= R) { tag[x] = va; val[x] = (r - l + 1) * w[va]; return; } int mid = (l + r) >> 1; if(L <= mid)modify(ls[x],l,mid,L,R,va); if(R > mid)modify(rs[x],mid + 1,r,L,R,va); val[x] = val[ls[x]] + val[rs[x]]; } inline void Cpushdown(int x) { if(!tag[x])return; int v = tag[x],tmp;tag[x] = 0; tmp = ls[x],ls[x] = ++dfn;ls[ls[x]] = ls[tmp],rs[ls[x]] = rs[tmp],tag[ls[x]] = tag[tmp],val[ls[x]] = val[tmp]; tmp = rs[x],rs[x] = ++dfn;ls[rs[x]] = ls[tmp],rs[rs[x]] = rs[tmp],tag[rs[x]] = tag[tmp],val[rs[x]] = val[tmp]; tag[ls[x]] = tag[rs[x]] = v; } inline void insert(int &x,int l,int r,int L,int R,int va,int flg) { if(flg) { int p = x; x = ++dfn; ls[x] = ls[p],rs[x] = rs[p],tag[x] = tag[p],val[x] = val[p]; } flg = 1; if(l < r && tag[x])Cpushdown(x),flg = 0; if(L <= l && r <= R){tag[x] = va;return;} int mid = (l + r) >> 1; if(L <= mid)insert(ls[x],l,mid,L,R,va,flg); if(R > mid)insert(rs[x],mid + 1,r,L,R,va,flg); } int main() { n=read();m=read();ty=read(); int ans=0; while(m--) { int op=read(); if (op==1) { int l=(read()+ans*ty)%n+1,r=(read()+ans*ty)%n+1; if (l>r) swap(l,r); printf("%d ",ans=query(rt,1,n,l,r)); } else if (op==2) { int l=(read()+ans*ty)%n+1,id=qid_2(rt,1,n,l); id=qid_1(root[id-1],1,n,l); modify(rt,1,n,l,l,id); tot++;root[tot]=root[tot-1]; insert(root[tot],1,n,l,l,id,1); } else { int l=(read()+ans*ty)%n+1,r=(read()+ans*ty)%n+1,x=read(); if (l>r) swap(l,r); tot++;w[tot]=x;root[tot]=root[tot-1]; insert(root[tot],1,n,l,r,tot,1); modify(rt,1,n,l,r,tot); } } }