• [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
    ",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
    ",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
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    jQuery 如何存储,获取和删除 Cookies
    mysql调用存储过程出现Illegal mix of collations错误
    vim IDE
    android 播放Raw文件夹下的音乐文件
    7种形式的Android Dialog使用举例
    Chronometer 计时器使用
    获取屏幕,适应屏幕
    android 碎片
    安卓开发者必备的42个链接
    自定义TabActivity,TabActivity的美化
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7521816.html
Copyright © 2020-2023  润新知