题目链接: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时,贡献对应减少。
(史前巨坑,负数取模,WA到吐,怀疑人生。。。以后遇到取模的时候要注意QAQ)
附上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<<" "; 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<<" "; 93 } 94 return 0; 95 }