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;
}

 

posted @ 2023-10-22 09:50  JMXZ  阅读(10)  评论(0)    收藏  举报