2020牛客寒假算法基础集训营3 G.牛牛的Link Power II (树状数组维护前缀和)

https://ac.nowcoder.com/acm/contest/3004/G

发现每个“1”对于它本身位置产生的影响贡献为0,对前面的“1”有产生贡献,对后面的"1"也产生贡献,用三个树状数组去维护,第一个维护“1”的个数,第二个每个“1”的位置,第三个维护“1”的贡献的前缀和,对于每个“1”的贡献,计算出对前面1的贡献和对后面1的贡献,之和在第一个树状数组中更新这个位置1的个数,第二个树状数组中更新这个1的pos,第三个树状数组中就是更新这个“1”对答案的贡献了
 
 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const ll mod = 1e9+7;
 5 const int maxn = 1e5+5;
 6 ll c1[maxn],c2[maxn],c3[maxn];
 7 int n;
 8 ll lowbit(ll x){
 9   return x&-x;
10 }
11 void add1(ll x, ll k) {
12   while (x <= n) {  //不能越界
13     c1[x] = c1[x] + k;
14     x = x + lowbit(x);
15   }
16 }
17 void add2(ll x, ll k) {
18   while (x <= n) {  //不能越界
19     c2[x] = (c2[x] + k);
20     x = x + lowbit(x);
21   }
22 }
23 void add3(ll x,ll k){
24   while (x <= n) {  //不能越界
25     c3[x] = (c3[x] + k);
26     x = x + lowbit(x);
27   }
28 }
29 ll getsum1(int x) {  // a[1]……a[x]的和
30   ll ans = 0;
31   while (x >= 1) {
32     ans = ans + c1[x];
33     x = x - lowbit(x);
34   }
35   return ans;
36 }
37 ll getsum2(int x) {  // a[1]……a[x]的和
38   ll ans = 0;
39   while (x >= 1) {
40     ans = (ans + c2[x]);
41     x = x - lowbit(x);
42   }
43   return ans;
44 }
45 ll getsum3(int x) {  // a[1]……a[x]的和
46   ll ans = 0;
47   while (x >= 1) {
48     ans = (ans + c3[x]);
49     x = x - lowbit(x);
50   }
51   return ans;
52 }
53 int main()
54 {
55     scanf("%d",&n);
56     string s;
57     cin>>s;
58     ll pos = 0,ans = 0,cnt = 0;
59     for(int i = 0;i<n;i++){
60         if(s[i] == '1') add1(i+1,1),add2(i+1,i+1);
61     }
62     ll t = 0;
63     for(int i = 0;i<n;i++){
64         if(s[i] == '1') cnt++,t = (t + i + 1),ans = ( cnt*(i+1) - t ),add3(i+1,ans);
65     }   //  pos = (pos + i)%mod,cnt++,ans = (ans + cnt*i-pos)%mod;
66     int m;scanf("%d",&m);
67     printf("%lld\n",getsum3(n)%mod);
68     while(m--){
69         ll q,pos;
70         cin>>q>>pos;
71         if(q == 1){
72             add1(pos,1);
73             add2(pos,pos);
74             ll tmp = getsum1(pos)*pos-getsum2(pos);
75             tmp = ( tmp + (getsum2(n)-getsum2(pos) - (getsum1(n)-getsum1(pos))*pos)) ;
76             add3(pos,tmp);
77         }
78         else{
79             ll tmp = getsum1(pos)*pos-getsum2(pos);
80             tmp = ( tmp + (getsum2(n)-getsum2(pos) - (getsum1(n)-getsum1(pos))*pos)) ;
81             add3(pos,-tmp);
82             add1(pos,-1);
83             add2(pos,-(pos));
84         }
85         ll ans = getsum3(n)%mod;
86         printf("%lld\n",ans);
87     }
88     return 0;
89 }
 

猜你喜欢

转载自www.cnblogs.com/AaronChang/p/12308585.html