codevs 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>
#define Max 100000
struct node
{
    int l,r,flag,num[8];
}tr[Max<<2|1];
int n,m,a;
void up(int k)
{
    for(int i=0;i<=6;i++)
    tr[k].num[i]=tr[k<<1].num[i]+tr[k<<1|1].num[i];
}
void read(int &x)
{
    x=0;bool f=1;
    char ch=getchar();
    while(ch>'9'||ch<'0')
    {
        if(ch=='-') f=0;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+(int)ch-48;
        ch=getchar();
    }
    x=f?x:(~x)+1;
}
void build(int k,int l,int r)
{
    tr[k].l=l;tr[k].r=r;
    if(l==r)
    {
        read(a);
        tr[k].num[a%7]++;
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    up(k);
}
void pushdown(int k)
{
    if(tr[k].l==tr[k].r) return;
    int tmp[8];
    tr[k<<1].flag+=tr[k].flag;
    tr[k<<1|1].flag+=tr[k].flag;
    for(int i=0;i<=6;i++) tmp[i]=tr[k<<1].num[i];
    for(int i=0;i<=6;i++)
    {
        tr[k<<1].num[(i+tr[k].flag)%7]=tmp[i];
        tmp[i]=tr[k<<1|1].num[i];
    }
    for(int i=0;i<=6;i++) tr[k<<1|1].num[(i+tr[k].flag)%7]=tmp[i];
    tr[k].flag=0;
}
int section_query(int k,int l,int r)
{
    if(tr[k].l==l&&tr[k].r==r) return tr[k].num[0];
    if(tr[k].flag) pushdown(k);
    int mid=(tr[k].l+tr[k].r)>>1;
    if(l>mid) return section_query(k<<1|1,l,r);
    else if(r<=mid) return section_query(k<<1,l,r);
    else return section_query(k<<1,l,mid)+section_query(k<<1|1,mid+1,r);
}
void section_change(int k,int l,int r,int v)
{
    if(tr[k].l==l&&tr[k].r==r)
    {
        int tmp[8];
        for(int i=0;i<=6;i++) tmp[i]=tr[k].num[i];
        for(int i=0;i<=6;i++) tr[k].num[(i+v)%7]=tmp[i];
        tr[k].flag+=v;
        return;
    }
    if(tr[k].flag) pushdown(k);
    int mid=(tr[k].l+tr[k].r)>>1;
    if(l>mid) section_change(k<<1|1,l,r,v);
    else if(r<=mid) section_change(k<<1,l,r,v);
    else section_change(k<<1,l,mid,v),section_change(k<<1|1,mid+1,r,v);
    up(k);
}
int main()
{
    read(n);
    build(1,1,n);
    read(m);
    char str[11];
    for(int x,y,z;m--;)
    {
        scanf("%s",str+1);
        if(str[1]=='c')
        {
            read(x);read(y);
            printf("%d\n",section_query(1,x,y));
        }
        else if(str[1]=='a')
        {
            read(x);read(y);read(z);
            section_change(1,x,y,z);
        }
    }
    return 0;
}

 

posted @ 2017-04-23 20:13  杀猪状元  阅读(123)  评论(0编辑  收藏  举报