分块试水--CODEVS5037 线段树练习4加强版

Posted Blue233333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分块试水--CODEVS5037 线段树练习4加强版相关的知识,希望对你有一定的参考价值。

感觉这才算入门题吧。。前面那些线段树练习,改几个字符就过了一定要搞成几道题。。

n<=2e5的数列,给常数K<=2e5,m<=2e5个操作,区间加,问一个区间里K的倍数。

这题空间???当成512MB吧。。n*sqrt(n)开得下

每个块记cnt(x,i)表示第x个块有多少数%K=i,以及整块+标记add(x),然后回答询问时默认一个块里的数都加上了add(x)即可,修改常规。

技术分享图片
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<string.h>
 4 #include<stdlib.h>
 5 #include<math.h>
 6 //#include<iostream>
 7 using namespace std;
 8 
 9 int n,m,q,K;
10 #define maxn 200011
11 #define maxm 461
12 int cnt[maxm][maxn],a[maxn],bel[maxn],tot,add[maxm];
13 void modify(int x,int y,int v)
14 {
15     if (bel[x]==bel[y])
16         for (int i=x;i<=y;i++) cnt[bel[i]][a[i]]--,a[i]+=v,a[i]%=K,cnt[bel[i]][a[i]]++;
17     else
18     {
19         for (int i=bel[x]+1;i<bel[y];i++) add[i]+=v,add[i]%=K;
20         for (int i=x;bel[i]==bel[x];i++) cnt[bel[i]][a[i]]--,a[i]+=v,a[i]%=K,cnt[bel[i]][a[i]]++;
21         for (int i=y;bel[i]==bel[y];i--) cnt[bel[i]][a[i]]--,a[i]+=v,a[i]%=K,cnt[bel[i]][a[i]]++;
22     }
23 }
24 int query(int x,int y)
25 {
26     int ans=0;
27     if (bel[x]==bel[y])
28         for (int i=x;i<=y;i++) ans+=(a[i]+add[bel[i]]==0 || a[i]+add[bel[i]]==K);
29     else
30     {
31         for (int i=bel[x]+1;i<bel[y];i++) ans+=cnt[i][add[i]?K-add[i]:0];
32         for (int i=x;bel[x]==bel[i];i++) ans+=(a[i]+add[bel[i]]==0 || a[i]+add[bel[i]]==K);
33         for (int i=y;bel[y]==bel[i];i--) ans+=(a[i]+add[bel[i]]==0 || a[i]+add[bel[i]]==K);
34     }
35     return ans;
36 }
37 
38 bool isdigit(char c) {return c>=0 && c<=9;}
39 int qread()
40 {
41     char c;int s=0;while (!isdigit(c=getchar()));
42     do s=s*10+c-0; while (isdigit(c=getchar())); return s;
43 }
44 int main()
45 {
46     n=qread(),q=qread(),K=qread();
47     m=(int)sqrt(n);
48     for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1;
49     tot=bel[n];
50     
51     for (int i=1;i<=n;i++)
52     {
53         a[i]=qread()%K;
54         cnt[bel[i]][a[i]]++;
55     }
56     
57     char c;
58     for (int i=1,x,y,z;i<=q;i++)
59     {
60         while (!((c=getchar())>=a && c<=z));
61         if (c==a)
62         {
63             x=qread(),y=qread(),z=qread();
64             modify(x,y,z);
65         }
66         else
67         {
68             x=qread(),y=qread();
69             printf("%d\n",query(x,y));
70         }
71         while (c>=a && c<=z) c=getchar();
72     }
73     return 0;
74 }
View Code

 

以上是关于分块试水--CODEVS5037 线段树练习4加强版的主要内容,如果未能解决你的问题,请参考以下文章

bzoj5037 线段树练习4加强版(暴力分块)

[Codevs] 1081 线段树练习 2 ----“分块!”

codevs 1082 线段树练习 3 --分块练习

codevs 4919 线段树练习4

codevs4919 线段树练习4

[CodeVS4919]线段树练习4