A Simple Problem with Integers (叶子节点 循环节)

链接:https://www.nowcoder.com/acm/contest/163/H
来源:牛客网
 

题目描述

You have N integers A1, A2, ... , AN. You are asked to write a program to receive and execute two kinds of instructions:

1. C a b means performing Ai = (Ai2 mod 2018) for all Ai such that a ≤ i ≤ b.
2. Q a b means query the sum of Aa, Aa+1, ..., Ab. Note that the sum is not taken modulo 2018.

输入描述:

The first line of the input is T(1≤ T ≤ 20), which stands for the number of test cases you need to solve.
The first line of each test case contains N (1 ≤ N ≤ 50000).The second line contains N numbers, the initial values of A1, A2, ..., An.  0 ≤ Ai < 2018. The third line contains the number of operations Q (0 ≤ Q ≤ 50000). The following Q lines represents an operation having the format "C a b" or "Q a b", which has been described above. 1 ≤ a ≤ b ≤ N.

输出描述:

For each test case, print a line "Case #t:" (without quotes, t means the index of the test case) at the beginning.
You need to answer all Q commands in order. One answer in a line.

示例1

输入

复制

1
8
17 239 17 239 50 234 478 43
10
Q 2 6
C 2 7
C 3 4
Q 4 7
C 5 8
Q 6 7
C 1 8
Q 2 5
Q 3 4
Q 1 8

输出

复制

Case #1:
779
2507
952
6749
3486
9937
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)

const int maxn=5e4+10;
int A[maxn];

//loop循环节里面对应的值
//th每个数字开始循环节的位置
//len每个数字循环节的长度
int loop[2200][20],th[2200],len[2200];
int lp[2200];
int vis[2200];
void init(){
    for(int i=0;i<=2018;i++){
        memset(vis,-1,sizeof(vis));
        int tmp=i;

        for(int j=0;;j++){
            lp[j]=tmp;
            if(vis[tmp]!=-1){
                th[i]=vis[tmp];
                len[i]=j-vis[tmp];
                rep(k,0,len[i])loop[i][k]=lp[th[i]+k];
                break;
            }
            else {
                vis[tmp]=j;
                tmp=tmp*tmp%2018;
            }
        }
      //  printf("i:%d th:%d len:%d\n",i,th[i],len[i]);
    }
}


int lazy[maxn<<2],thsh[maxn<<2];
int res[maxn<<2],sum[maxn<<2][6];

void pushup(int o){
    res[o]=res[ls(o)]+res[rs(o)];
    thsh[o]=max(thsh[ls(o)],thsh[rs(o)]);
    rep(i,0,6)sum[o][i]=sum[ls(o)][i]+sum[rs(o)][i];
}

void build(int l,int r,int o){

   // printf("l:%d r:%d o:%d \n",l,r,o);
    lazy[o]=0;
    if(l==r){
       // printf("o:%d len:%d A:%d\n",o,len[A[l]],A[l]);
        thsh[o]=th[A[l]];
        res[o]=A[l];
        rep(i,0,6) sum[o][i]=loop[A[l]][i%len[A[l]]];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,ls(o));
    build(mid+1,r,rs(o));
    pushup(o);
}

//如果说这棵子树上的值都已经过了阀值,我们只需要在树根上移移位置就好了,下面都是循环节了
int v[10];
void move(int o,int val){
    rep(i,0,6) v[(i+6-val)%6]=sum[o][i];
    rep(i,0,6) sum[o][i]=v[i];
    res[o]=sum[o][0];

    lazy[o]+=val;
    lazy[o]%=6;
}

void pushdown(int o){
    move(ls(o),lazy[o]);
    move(rs(o),lazy[o]);
    lazy[o]=0;
}

void update(int L,int R,int O,int y1,int y2){
    //如果说下面的都已经超过了阀值,这样我们就可以直接移动数值了
    if(!thsh[O]&&y1<=L&&R<=y2){
        move(O,1);//已经过了阀值,我们可以直接在上面移动就好了
        return;
    }
    //如果下面还有没到阀值的,就一直更新到叶子节点
    if(L==R){
        thsh[O]--;
        res[O]=res[O]*res[O]%2018;
        return;
    }
    if(lazy[O])pushdown(O);
    int mid=(L+R)>>1;
    if(y1<=mid)update(L,mid,ls(O),y1,y2);
    if(y2>mid) update(mid+1,R,rs(O),y1,y2);
    pushup(O);
}

int query(int l,int r,int o,int y1,int y2){
    if(y1<=l&&r<=y2)return res[o];

    if(lazy[o])pushdown(o);
    int mid=(l+r)>>1;
    int ans=0;
    if(y1<=mid)ans+=query(l,mid,ls(o),y1,y2);
    if(y2>mid) ans+=query(mid+1,r,rs(o),y1,y2);
    return ans;
}

int main(){
    init();
    int T;
    scanf("%d",&T);
    rep(kase,0,T){
        int n;
        scanf("%d",&n);
        rep(i,1,n+1)scanf("%d",&A[i]);
        build(1,n,1);
        printf("Case #%d:\n",kase+1);
        int m;
        scanf("%d",&m);
        rep(i,0,m){
            char ch;int l,r;
            scanf(" %c %d %d",&ch,&l,&r);
            if(ch=='Q')  printf("%d\n",query(1,n,1,l,r));
            else update(1,n,1,l,r);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/81461523