4919 线段树练习4

 

 时间限制: 1 s
 空间限制: 128000 KB
 
 
 
题目描述 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

这道题的比较裸,需要思考的只有如何pushup和change信息。

对于线段树里存的元素是一个桶,记录这一段余数为1,2,3,4,5,6,0的分别有多少。

在pushup时只需将ls和rs的桶相加即可(代码11行)

在修改时则只需将数组内的是s[i]元素想右移动s[(i+a)%7]即可.

其他基本与普通线段树无异。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define ls x<<1
 4 #define rs x<<1|1
 5 const int N=100005;
 6 int lazy[N<<2];
 7 struct X
 8 {
 9     int s[7];
10     X() {memset(s,0,sizeof(s));};
11     void pu(const X &a,const X &b)
12     {
13         for(int i=0;i<7;i++)
14             s[i]=a.s[i]+b.s[i];
15     }
16     void gb(int x)
17     {
18         X t;
19         for(int i=0;i<7;i++) t.s[(i+x)%7]=s[i];
20         *this=t;
21     }
22 }tree[N<<2];
23 char c[6];
24 void pd(int x)
25 {
26     if(lazy[x])
27     {
28         lazy[ls]+=lazy[x];
29         lazy[rs]+=lazy[x];
30         tree[ls].gb(lazy[x]);
31         tree[rs].gb(lazy[x]);
32         lazy[x]=0;
33     }
34 }
35 void bu(int l,int r,int x)
36 {
37     if(l==r) 
38     {
39         int a;
40         scanf("%d",&a);
41         tree[x].s[a%7]=1;
42     }
43     else
44     {
45         int mid=(l+r)>>1;
46         bu(l,mid,ls);
47         bu(mid+1,r,rs);
48         tree[x].pu(tree[ls],tree[rs]);
49     }
50 }
51 void chan(int l,int r,int x,int s,int ql,int qr)
52 {
53     if(ql<=l&&qr>=r) lazy[x]+=s,tree[x].gb(s);
54     else
55     {
56         int mid=(l+r)>>1;
57         pd(x);
58         if(mid>=ql) chan(l,mid,ls,s,ql,qr);
59         if(qr>mid) chan(mid+1,r,rs,s,ql,qr);
60         tree[x].pu(tree[ls],tree[rs]);
61     }
62 }
63 int ask(int l,int r,int x,int ql,int qr)
64 {
65     if(ql<=l&&qr>=r) return tree[x].s[0];
66     else
67     {
68         int mid=(l+r)>>1,re=0;
69         pd(x);
70         if(mid>=ql) re+=ask(l,mid,ls,ql,qr);
71         if(qr>mid) re+=ask(mid+1,r,rs,ql,qr);
72         tree[x].pu(tree[ls],tree[rs]);
73         return re;
74     }
75 }
76 int main()
77 {
78     int n,q;
79     scanf("%d",&n);
80     bu(1,n,1);
81     scanf("%d",&q);
82     while(q--)
83     {
84         scanf("%s",c);
85         if(c[0]=='a')
86         {
87             int tj,l,r;
88             scanf("%d%d%d",&l,&r,&tj);
89             chan(1,n,1,tj,l,r);
90         }
91         else
92         {
93             int l,r;
94             scanf("%d%d",&l,&r);
95             printf("%d\n",ask(1,n,1,l,r));
96         }
97     }
98     return 0;
99 }