2020牛客寒假算法基础集训营3【F、G】-牛牛的Link Power I/II(线段树)

题目链接:F:https://ac.nowcoder.com/acm/contest/3004/F

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

先讲F:

从前向后遍历,每遇到一个1就先增加当前贡献值然后记录当前个数,遇到每个数字增加当前1的个数作为贡献值。也可以计算前缀和的前缀和等方法。

然后是G:

在F的基础上用线段树维护对应区间1的个数cnt和下标总和ind。当pos下标的数字从0变为1时,左边的贡献增加pos*2-(cnt+ind),右边的贡献增加(cnt+ind)-pos*2。(cnt和ind分别指对应区间的值);当pos下标的数字从1变为0时,贡献对应减少。

附上G题代码(F题就是main函数上半部分):

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef pair<ll,ll> pll;
 5 const int mod=1e9+7,maxn=1e5+10;
 6 inline int ls(signed x){return x<<1;}
 7 inline int rs(signed x){return x<<1|1;}
 8 struct Node{
 9     int l,r;
10     ll val;
11 };
12 Node cnt[maxn<<2];
13 Node ind[maxn<<2];
14 char ch[maxn];
15 ll pls(ll a,ll b){//有坑,防止a+b是负数
16     return ((a+b)%mod+mod)%mod;
17 }
18 void pushup(int root){
19     cnt[root].val=pls(cnt[ls(root)].val,cnt[rs(root)].val);
20     ind[root].val=pls(ind[ls(root)].val,ind[rs(root)].val);
21 }
22 void build(int root,int l,int r){
23     cnt[root].l=ind[root].l=l;
24     cnt[root].r=ind[root].r=r;
25     if(l==r){
26         if(ch[l]=='1'){
27             cnt[root].val=1;
28             ind[root].val=l;
29         }else{
30             cnt[root].val=ind[root].val=0;
31         }
32         return;
33     }
34     int mid=(l+r)>>1;
35     build(ls(root),l,mid);
36     build(rs(root),mid+1,r);
37     pushup(root);
38 }
39 void update(int root,int l,int r,int pos){
40     if(l==r){
41         cnt[root].val=1-cnt[root].val;
42         ind[root].val=l-ind[root].val;
43         return;
44     }
45     int mid=(l+r)>>1;
46     if(pos<=mid)update(ls(root),l,mid,pos);
47     else update(rs(root),mid+1,r,pos);
48     pushup(root);
49 }
50 pll operator +(pll a,pll b){
51     return {pls(a.first,b.first),pls(a.second,b.second)};
52 }
53 pll query(int root,int l,int r){
54     assert(r>=l);
55     int mid=(cnt[root].l+cnt[root].r)>>1;
56     if(cnt[root].l==l&&cnt[root].r==r)
57         return {cnt[root].val,ind[root].val};
58     if(mid>=r)return query(ls(root),l,r);
59     else if(mid<l)return query(rs(root),l,r);
60     else return query(ls(root),l,mid)+query(rs(root),mid+1,r);
61 }
62 int main(){
63     int n;
64     scanf("%d%s",&n,ch+1);
65     build(1,1,n);
66     ll cont=0,t=0,res=0;
67     for(int i=1;i<=n;i++){
68         if(ch[i]=='1'){
69             res=pls(res,t);
70             cont++;
71         }
72         t=pls(cont,t);
73     }
74     cout<<res<<"\n";
75     int m;
76     cin>>m;
77     while(m--){
78         int q,pos;
79         cin>>q>>pos;
80         update(1,1,n,pos);
81         if(q==1){
82             pll a(0,0),b(0,0);
83             if(pos!=1)a=query(1,1,pos-1);
84             if(pos!=n)b=query(1,pos+1,n);
85             res=pls(res,pos*a.first-a.second-pos*b.first+b.second);
86         }else{
87             pll a(0,0),b(0,0);
88             if(pos!=1)a=query(1,1,pos-1);
89             if(pos!=n)b=query(1,pos+1,n);
90             res=pls(res,-(pos*a.first-a.second-pos*b.first+b.second));
91         }
92         cout<<res<<"\n";
93     }
94     return 0;
95 }

猜你喜欢

转载自www.cnblogs.com/charles1999/p/12285143.html