Codevs-4919 线段树练习4(区间加上一个值并求摸个区间整除k的数的个数,线段树+数组维护)

Posted StarHai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codevs-4919 线段树练习4(区间加上一个值并求摸个区间整除k的数的个数,线段树+数组维护)相关的知识,希望对你有一定的参考价值。

给你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

题解:和普通线段树区间修改以及区间求和差不多,只是我们这里用数组来存储每个区间对 K取余后的数的每个的数量即可;其他操作和普通线段树相同;

参考代码:

技术分享图片
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<stack>
  9 #include<set>
 10 #include<vector>
 11 #include<map>
 12 using namespace std;
 13 typedef long long LL;
 14 const int INF=0x3f3f3f3f;
 15 const LL inf=0x3f3f3f3f3f3f3f3fLL;
 16 const int maxn=1e5+10;
 17 int n,q,c[maxn],a,b,x,temp[7];
 18 string str;
 19 
 20 struct Node{
 21     int l,r,tag,mod[7];
 22 } tree[maxn<<2];
 23 
 24 void build(int pos,int l,int r)
 25 {
 26     tree[pos].l=l,tree[pos].r=r,tree[pos].tag=0;
 27     for(int i=0;i<7;i++) tree[pos].mod[i]=0;
 28     if(l==r)
 29     {
 30         tree[pos].mod[c[l]%7]=1;
 31         return ;
 32     }
 33     int mid=(tree[pos].l+tree[pos].r)>>1;
 34     build(pos<<1,l,mid);
 35     build(pos<<1|1,mid+1,r);
 36     for(int i=0;i<7;i++) tree[pos].mod[i]=tree[pos<<1].mod[i]+tree[pos<<1|1].mod[i];
 37 }
 38 
 39 void change(int pos,int x)
 40 {
 41     for(int i=0;i<7;i++) temp[(i+x)%7]=tree[pos].mod[i];
 42     for(int i=0;i<7;i++) tree[pos].mod[i]=temp[i];
 43 }
 44 
 45 void pushup(int pos)
 46 {
 47     for(int i=0;i<7;i++) 
 48         tree[pos].mod[i]=tree[pos<<1].mod[i]+tree[pos<<1|1].mod[i];
 49 }
 50 
 51 void pushdown(int pos)
 52 {
 53     if(tree[pos].l==tree[pos].r) return ;
 54     tree[pos<<1].tag+=tree[pos].tag;
 55     tree[pos<<1|1].tag+=tree[pos].tag;
 56     change(pos<<1,tree[pos].tag),change(pos<<1|1,tree[pos].tag);
 57     tree[pos].tag=0;
 58 }
 59 
 60 void update(int pos,int l,int r,int x)
 61 {
 62     if(tree[pos].tag) pushdown(pos);
 63     if(tree[pos].l==l&&tree[pos].r==r)
 64     {
 65         tree[pos].tag+=x;change(pos,x);
 66         return ;
 67     }
 68     int mid=(tree[pos].l+tree[pos].r)>>1;
 69     if(r<=mid) update(pos<<1,l,r,x);
 70     else if(l>=mid+1) update(pos<<1|1,l,r,x);
 71     else update(pos<<1,l,mid,x),update(pos<<1|1,mid+1,r,x);
 72     pushup(pos);
 73 }
 74 
 75 int query(int pos,int l,int r)
 76 {
 77     if(tree[pos].tag) pushdown(pos);
 78     if(tree[pos].l==l&&tree[pos].r==r) return tree[pos].mod[0];
 79     int mid=(tree[pos].l+tree[pos].r)>>1;
 80     if(r<=mid) return query(pos<<1,l,r);
 81     else if(l>=mid+1) return query(pos<<1|1,l,r);
 82     else return query(pos<<1,l,mid)+query(pos<<1|1,mid+1,r);    
 83 }
 84 
 85 int main()
 86 {
 87     ios::sync_with_stdio(false);
 88     cin>>n;
 89     for(int i=1;i<=n;i++) cin>>c[i];
 90     build(1,1,n);
 91     cin>>q;
 92     while(q--)
 93     {
 94         cin>>str;
 95         if(str[0]==a)
 96         {
 97             cin>>a>>b>>x;
 98             update(1,a,b,x);
 99         }
100         else if(str[0]==c)
101         {
102             cin>>a>>b;
103             cout<<query(1,a,b)<<endl;
104         }
105     }
106     
107     return 0;
108 }
View Code

 

以上是关于Codevs-4919 线段树练习4(区间加上一个值并求摸个区间整除k的数的个数,线段树+数组维护)的主要内容,如果未能解决你的问题,请参考以下文章

codevs 4919 线段树练习4

codevs 4919 线段树练习4

codevs 4919 线段树练习4

[CodeVS4919]线段树练习4

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

codves 4919 线段树练习4