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

题意:

给一个字符串,求所有1之间距离的和,之后给q组修改,每次把一个位置上的0改成1或者1改成0,求出每次修改之后的答案

思路:

cnti 为从1到i这段字符串中1的个数,sum为从1到i中1位置的和

假设修改的位置为i,这答案的改变值为[cnt(1-i) * i - sum(1-i)] + [sum(i+1 - n) - i*cnt(i+1 - n)]

特别要注意取模的问题:(ans%mod+mod)%mod;

#include<iostream>
#include<algorithm>
 using namespace std;
 typedef long long ll;
 const int maxn=1e5+10;
 const int mod=1e9+7;
 char s[maxn];
 ll num[maxn],sum[maxn];
 int n,m;
  int lowbit(int x){return x&(-x);}
  void add(int x,ll val)
  {
      while(x<=maxn){
          sum[x]+=val;
          x+=lowbit(x);
      }
  }
  ll query(int x)//算sum 
  {
      ll ans=0;
      while(x>=1){
          ans+=sum[x];
          x-=lowbit(x);
          ans%=mod;
      }
      return ans%mod;
}
  void add1(int x,ll val)
  {
      while(x<=maxn){
          num[x]+=val;
          x+=lowbit(x);
    }
 }
  ll query1(int x)//算cnt 
  {
      ll ans=0;
      while(x>=1){
          ans+=num[x];
          x-=lowbit(x);
      }
      return ans%mod;
  }
  int main()
  {
      scanf("%d%s",&n,s+1);
      ll ans=0,cnt=0,su=0;
      for(int i=1;i<=n;i++){
          if(s[i]=='1'){
              ans+=(cnt*i-su)%mod;
             cnt++;
             su+=i;
             ans%=mod,su%=mod;
              add(i,i);
              add1(i,1);
          }
      }
    cout<<(ans%mod+mod)%mod<<endl;
    scanf("%d",&m);
    while(m--){
        int op,pos;
        scanf("%d%d",&op,&pos);
        if(op==1){
            if(s[pos]=='1')    continue;
            else{
                ll xx=pos*query1(pos-1)-query(pos-1)+(query(n)-query(pos))-pos*(query1(n)-query1(pos));
                ans+=xx%mod;
                add(pos,pos),add1(pos,1);
                cout<<(ans%mod+mod)%mod<<endl;
                s[pos]='1';
            }
        }
        else{
            if(s[pos]=='0')    continue;
            else{
                ll xx=pos*query1(pos-1)-query(pos-1)+(query(n)-query(pos))-pos*(query1(n)-query1(pos));
                ans-=xx%mod;
                add(pos,-pos),add1(pos,-1);
                cout<<(ans%mod+mod)%mod<<endl;
                s[pos]='0';
            }
        }
    }
    return 0;
  }

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12284523.html