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