[Codevs] 5037 线段树练习4加强版

5037 线段树练习4加强版

 时间限制: 4 s
 空间限制: 256000 KB
 题目等级 : 钻石 Diamond
 
 
题目描述 Description

维护一个序列,要求支持下列2种操作:

add a b c:区间[a,b]中每个数加上c

count a b:查询区间[a,b]中有多少数是k的倍数(k为给定常数)

 
输入描述 Input Description

第一行三个数n,m,k,分别表示序列长度、操作数和count中的k

接下来一行n个整数,表示原始序列

接下来m行,每行是题面中的操作之一

 
输出描述 Output Description

对于每个count操作,输出一行答案

 
样例输入 Sample Input

10 10 5

5 5 8 3 5 6 7 8 3 0

add 2 7 1

count 3 4

add 2 5 4

count 1 5

count 2 6

count 1 3

add 4 8 3

count 3 7

add 4 8 2

count 1 2

 
样例输出 Sample Output

0

3

2

2

1

2

 
数据范围及提示 Data Size & Hint

10%:n,m<=10,k<=10000;

另外的20%:n,m<=100000,k<=10;

另外的20%:n,m<=50000,k<=100;

100%:n,m<=200000,k<=200000.

 

分析 Analysis

分块!

拿线段树练习4 的代码改了改就过了

模型和线段树练习4是一样的,只不过改了取模数的范围

 

代码 Code

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #define maxn 1000000
 5 using namespace std;
 6 
 7 char str[10];
 8 int block[maxn],k,mod[450][200010],size,arr[maxn],add[450],bdd[450],n,m;
 9 
10 void modify(){
11     int a,b,c;
12     scanf("%d%d%d",&a,&b,&c);
13     a--,b--,c %= k;
14     if(!c) return;
15     
16     if(block[a] == block[b]){
17         for(int i = a;i <= b;i++){
18             mod[block[i]][arr[i]]--;
19             arr[i] = (arr[i]+c)%k;
20             mod[block[i]][arr[i]]++;
21         }
22     }else{
23         
24         for(int i = a;i <= block[a]*size-1;i++)
25             mod[block[i]][arr[i]]--,
26             arr[i] = (arr[i]+c)%k,
27             mod[block[i]][arr[i]]++;
28         for(int i = (block[b]-1)*size;i <= b;i++)
29             mod[block[i]][arr[i]]--,
30             arr[i] = (arr[i]+c)%k,
31             mod[block[i]][arr[i]]++;
32         for(int i = block[a]+1;i < block[b];i++)
33             add[i] = (add[i]+c)%k,
34             bdd[i] = (bdd[i]-c+k)%k;
35             
36     }
37 }
38 
39 void count(){
40     int a,b;
41     scanf("%d%d",&a,&b);
42     a--,b--;
43     int ans = 0;
44     
45     if(block[a] == block[b]){
46         for(int i = a;i <= b;i++)
47             ans += ((arr[i]+add[block[i]])%k)?0:1;
48     }else{
49         
50         for(int i = a;i <= block[a]*size-1;i++)
51             ans += ((arr[i]+add[block[i]])%k)?0:1;
52         for(int i = (block[b]-1)*size;i <= b;i++)
53             ans += ((arr[i]+add[block[i]])%k)?0:1;
54         for(int i = block[a]+1;i < block[b];i++)
55             ans += mod[i][bdd[i]];
56         
57     }
58     
59     printf("%d\n",ans);
60 }
61 
62 void show(){
63     for(int i = 0;i < n;i++){
64         printf("%d ",arr[i]+add[block[i]]);
65     }cout << endl;
66 }
67 
68 int main(){
69     scanf("%d%d%d",&n,&m,&k);
70     size = (int)sqrt(n)+1;
71     for(int i = 0;i < n;i++) block[i] = i/size+1;
72 //    for(int i = 0;i < n;i++) printf("#%d: block %d\n",i,block[i]);
73     for(int i = 0;i < n;i++){
74         scanf("%d",&arr[i]);
75         arr[i] %= k;
76         mod[block[i]][arr[i]]++;
77     }
78 //    show();
79     for(int i = 0;i < m;i++){
80         scanf("%s",str);
81         if(str[0] == 'a') modify();
82         else count();
83 //        show();
84     }
85     
86     return 0;
87 }
心情极差qwq

 

posted @ 2017-09-14 17:37  μSsia  阅读(201)  评论(0编辑  收藏  举报