CF1834F Typewriter
/* 3 2 3 1 0 1 ---------------------- 3 1 2 3 2 2 1 3 0 2 1 ------------------- 5 3 1 2 5 4 5 1 3 3 2 3 1 4 3 3 2 1 2 1 2 --------------- */ /* 通过置换环 知道 答案是 所有 pi<i 的数 所以统计一下就可以了 O(N^2) 每一个数 对 每次询问的答案 的贡献 是一个区间 所以可以预先处理 左右移动 翻转 操作 可以通过线段树实现 令线段树中 区间i位置是 右移 i位 的答案 1.若 pi<i 则贡献的区间 有 右移 1 位到 n-i 位 + n-i+pi+1---n 2.若 pi>=i 贡献区间 右移 pi-i+1---n-i 操作 直接查询 第step位 的 答案 即 右移i位的 答案 1.左移 + 2.右移 直接查询 第step位 的 答案 2.翻转 再建一棵树 进行查询 step=n-setp */ #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<string.h> //#include<queue> //#include<vector> //#include<bits/stdc++.h> #define ll long long #define ddd printf("-----------------------\n"); using namespace std; const int maxn=4e5 +10; const int mod=998244353; const int inf=0x3f3f3f3f; int n,q,p[maxn],rev[maxn]; struct seg_tree{ int sum[maxn<<2],add[maxn<<2]; //void build(int k,int l,int r){ // if(l==r){ // sum[k] // } //} void pushdown(int k,int l,int r) { if(add[k]==0) return; int mid=l+r>>1; add[k<<1]+=add[k],add[k<<1|1]+=add[k]; sum[k<<1]+=add[k]*(mid-l+1),sum[k<<1|1]+=add[k]*(r-mid); add[k]=0; } void area_add(int k,int l,int r,int x,int y,int val) { if(x>y) return; if(x<=l&&r<=y) { add[k]+=val; sum[k]+=(r-l+1)*val; return; } pushdown(k,l,r); int mid=l+r>>1; if(x<=mid) area_add(k<<1,l,mid,x,y,val); if(mid<y) area_add(k<<1|1,mid+1,r,x,y,val); sum[k]=sum[k<<1]+sum[k<<1|1]; } int query(int k,int l,int r,int x,int y) { if(x<=l&&r<=y) return sum[k]; pushdown(k,l,r); int mid=l+r>>1,res=0; if(x<=mid) res+=query(k<<1,l,mid,x,y);//!!!!!!!!!!!!!!!!!!!!!!!!! if(mid<y) res+=query(k<<1|1,mid+1,r,x,y); return res; } }t1,t2; int main() { ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) cin>>p[i]; for(int i=1;i<=n;i++) rev[i]=p[n+1-i]; for(int i=1;i<=n;i++) { if(i<=p[i]) t1.area_add(1,1,n,p[i]-i+1,n-i,1); else{ t1.area_add(1,1,n,1,n-i,1); t1.area_add(1,1,n,n-i+p[i]+1,n,1); } } for(int i=1;i<=n;i++) { if(i<=rev[i]) t2.area_add(1,1,n,rev[i]-i+1,n-i,1); else{ t2.area_add(1,1,n,1,n-i,1); t2.area_add(1,1,n,n-i+rev[i]+1,n,1); } } cout<<t1.query(1,1,n,n,n)<<'\n'; cin>>q; //cout<<"q:"<<q<<endl; int op,step=0,x,bz=0; while(q--) { cin>>op; if(op==1){ cin>>x; step=(step-x+n)%n; } else if(op==2){ cin>>x; step=(step+x)%n; } else{ bz^=1; // cin>> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! step=n-step; } step= step==0? n:step; //if(step==0) step=n; if(bz) cout<<t2.query(1,1,n,step,step)<<'\n'; else cout<<t1.query(1,1,n,step,step)<<'\n'; } return 0; }