1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 int array[100000]; 5 int f(int a1,int a2) 6 { 7 for(int i=a1;i<=a2;i++){ 8 array[i]=(int)(log(array[i])/log(2)+1); 9 } 10 int sum=0; 11 for(int i=0;i<sizeof(array)/sizeof(int);i++){ 12 sum+=array[i]; 13 } 14 return sum; 15 } 16 int main() 17 { 18 cin >> n >> m; 19 int ans[m]; 20 memset(array,0,sizeof(array)); 21 memset(ans,0,sizeof(ans)); 22 for(int i=0;i<n;i++){ 23 cin >> array[i]; 24 } 25 int a1,a2; 26 int t=0; 27 while(m--){ 28 cin >> a1 >> a2; 29 a1--; 30 a2--; 31 ans[t++]=f(a1,a2); 32 } 33 for(int i=0;i<t;i++){ 34 cout << ans[i] << endl; 35 } 36 }
里对区间里的值进行对数运算,可以看做是更新,区间更新,求和,很明显是线段树...
下面提供一个大佬的代码只供参考:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 6 7 const int maxn = 100010; 8 9 int num[maxn]; 10 11 int tree[maxn*2]; 12 13 int n,m; 14 15 int l,r; 16 17 int cnt; 18 19 20 21 22 23 void build(int x,int l, int r) 24 25 { 26 27 if (l == r){ 28 29 cin >> tree[x]; 30 31 if (tree[x] == 1){//统计数值1的个数 ,方便优化程序 32 33 cnt++; 34 35 tree[x] = 2;//将所有1均变为2,防止1干扰程序优化 36 37 } 38 39 return; 40 41 } 42 43 44 45 int mid = (l+r)/2; 46 47 build(x*2,l,mid); 48 49 build(x*2+1,mid+1,r); 50 51 tree[x] = tree[x*2]+tree[x*2+1]; 52 53 } 54 55 56 57 void update(int x,int l,int r,int L,int R) 58 59 { 60 61 if (tree[x] == (r-l+1)*2){ //如果全为2,直接返回 62 63 return ; 64 65 } 66 67 if (l == r){ 68 69 tree[x] = num[tree[x]]; 70 71 return; 72 73 } 74 75 76 77 int mid = (l+r)/2; 78 79 if (R <= mid) 80 81 update(x*2,l,mid,L,R); 82 83 else if (L > mid) 84 85 update(x*2+1,mid+1,r,L,R); 86 87 else{ 88 89 update(x*2,l,mid,L,mid); 90 91 update(x*2+1,mid+1,r,mid+1,R); 92 93 } 94 95 tree[x] = tree[x*2]+tree[x*2+1]; 96 97 } 98 99 100 101 int main() 102 103 { 104 105 for(int i = 1; i <= maxn; i++) //打表 106 107 num[i] = (int)(log2(i) + 1); 108 109 cin >> n >> m; 110 111 112 113 build(1,1,n); 114 115 while(m--){ 116 117 cin >> l >> r; 118 119 update(1,1,n,l,r); 120 121 cout << tree[1]-cnt << endl; 122 123 } 124 125 return 0; 126 127 }
原文:https://www.cnblogs.com/henuliulei/p/10909084.html