zoukankan      html  css  js  c++  java
  • codves 4919 线段树练习4

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
    题目描述 Description

    给你N个数,有两种操作

    1:给区间[a,b]内的所有数都增加X

    2:询问区间[a,b]能被7整除的个数
    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是add,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是count,表示统计区间[a,b]能被7整除的个数

    输出描述 Output Description

    对于每个询问输出一行一个答案

    样例输入 Sample Input

       

    3 
    2 3 4
    6
    count 1 3
    count 1 2
    add 1 3 2
    count 1 3
    add 1 3 3
    count 1 3

     

    样例输出 Sample Output

    0

    0

    0

    1

    数据范围及提示 Data Size & Hint

    10%:1<N<=10,1<Q<=10

    30%:1<N<=10000,1<Q<=10000

    100%:1<N<=100000,1<Q<=100000

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=100010;
    struct node
    {
        int lazy,l,r;
        int sum[8];
    }tr[N<<2];
    int arr[10];
    inline void pushup(int ro)
    {
        for(int i=0;i<=6;i++) tr[ro].sum[i]=tr[ro<<1].sum[i]+tr[ro<<1|1].sum[i];    
    }
    void build(int ro,int l,int r)
    {
        tr[ro].l=l,tr[ro].r=r;
        if(l==r)
        {
            int a;
            scanf("%d",&a);
            tr[ro].sum[a%7]++;
        }
        else
        {
            int mid=(l+r)>>1;
            build(ro<<1,l,mid);
            build(ro<<1|1,mid+1,r);
            pushup(ro);
        }
        return;
    }
    inline void down(int ro)
    {
        tr[ro<<1].lazy+=tr[ro].lazy;
        tr[ro<<1|1].lazy+=tr[ro].lazy;
        for(int i=0;i<=6;i++) arr[i]=0,arr[i]=tr[ro<<1].sum[i];
        for(int i=0;i<=6;i++) tr[ro<<1].sum[(i+tr[ro].lazy)%7]=arr[i];
        for(int i=0;i<=6;i++) arr[i]=0,arr[i]=tr[ro<<1|1].sum[i];
        for(int i=0;i<=6;i++) tr[ro<<1|1].sum[(i+tr[ro].lazy)%7]=arr[i];
        tr[ro].lazy=0;
    }
    void change(int ro,int l,int r,int add)
    {
        if(l<=tr[ro].l&&tr[ro].r<=r)
        {
            for(int i=0;i<=6;i++) arr[i]=0,arr[i]=tr[ro].sum[i];
            for(int i=0;i<=6;i++) tr[ro].sum[(i+add)%7]=arr[i];
            //printf("%d
    ",add);
            tr[ro].lazy+=add;
            tr[ro].lazy%=7;
            //for(int i=1;i<=20;i++) {for(int j=0;j<=6;j++) printf("%d ",tr[i].sum[j]);printf("%d %d
    ",tr[i].l,tr[i].r);}
            return;
        }
        if(tr[ro].lazy) down(ro);
        int mid=(tr[ro].l+tr[ro].r)>>1;
        if(l<=mid) change(ro<<1,l,r,add);
        if(mid<r)  change(ro<<1|1,l,r,add);
        pushup(ro);
        return;
    }
    long long int query(int ro,int l,int r)
    {
        if(l<=tr[ro].l&&tr[ro].r<=r) return tr[ro].sum[0];
        if(tr[ro].lazy) down(ro);
        long long int ans=0;
        int mid=(tr[ro].l+tr[ro].r)>>1;
        if(l<=mid)  ans+=query(ro<<1,l,r);
        if(r>mid)   ans+=query(ro<<1|1,l,r);
        return ans;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        build(1,1,n);
        //for(int i=1;i<=20;i++) {for(int j=0;j<=6;j++) printf("%d ",tr[i].sum[j]);printf("%d %d
    ",tr[i].l,tr[i].r);}
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            char pd[8];
            scanf("%s",pd);
            if(pd[0]=='a')
            {
                int a,b,x;
                scanf("%d %d %d",&a,&b,&x);
                change(1,a,b,x%7);
                //for(int k=1;k<=20;k++) {for(int j=0;j<=6;j++) printf("%d ",tr[k].sum[j]);printf("%d %d
    ",tr[k].l,tr[k].r);}
            }
            else
            {
                int l,r;
                scanf("%d %d",&l,&r);
                printf("%lld
    ",query(1,l,r));
            }
        }
        return 0;    
    }
    View Code

    关键是我们需要维护的东西是什么?

    我们用一个数组存区间内%7后每个值的个数;

    最后输出值为0的个数。

  • 相关阅读:
    P3803 【模板】多项式乘法(FFT)
    P2264 情书 Trie匹配
    CF877E Danil and a Part-time Job 线段树维护dfs序
    P3810 【模板】三维偏序(陌上花开)
    LOJ #6282. 数列分块入门 6
    LOJ #6281. 数列分块入门 5
    LOJ #6280. 数列分块入门 4
    LOJ #6279. 数列分块入门 3
    LOJ #6278. 数列分块入门 2
    LOJ #6277. 数列分块入门 1
  • 原文地址:https://www.cnblogs.com/12fs/p/7457535.html
Copyright © 2011-2022 走看看