[20190617] JZOJ6223相互膜

タイトル

小さな\(\)と小\(Bの\)の長さで(2N \)\の偶数位置のためのゲーム上記アレイ、奇数A、Bの初期位置

小さな\(A \)上部手、\(Iは\)人間の操作がされてもよい(私は\)\または\(I + 1 \)位置反転値(何もしなくてもよいです)

\(N-1 \)動作の終了後に、小\(\)全てのスコア\(\)小の重量及び位置\(B \)同様

たびに重み値は少しずつ、各小Aを尋ねるとなります

非負の重みを持つ$ N \ル200000 $、

問題の解決策

  • セット\(F_ {I、0/ 1} \) を表し\(Iは\)後方用位置\(Iは\)別の差ロケーションが反転されず、最大動作電流のスコアを
    \ [\開始{整列}& \ {iが0} {ケース} F_を開始\&= \最大\ {S_I - F_ {iは1,0} +、S_I - F_ {iは1,1} + \} \ \ F_ {I、1} \ &= \最大\ {S_I - F_ {iは-s_i、1,0} + - F_ {iは1,1} + \} \\ \端{ケース} \\& 配置\デルタ_i = F_ {I、0 } - F_ {I、1} \\& 起因S_I GE 0 \明らか\ delta_i \ GE 0 \\&\開始{ケース} F_ {I、0} \&= S_I - F_ {iは+ 1,1} \\ F_ { I、1} \&= maxの\ {2s_i - \ delta_ {iは、+ 1}、0 \} - S_I - F_ {I + 1,1} \\ \ delta_i \ &=分\ {2s_i、\ delta_ {I + 1} \} \端{ケース} \\&\ delta_n = 2s_n メンテナンスの\ delta_iサフィックス分\\&F_ {1,0} = 2s_iするものと解釈される \ sum_を{ I = 1} ^ {N} ( - 1)^ {I-1} S_I + \ sum_ {i = 2} ^ {n}は(-1)^ iは\端{整列} \\ delta_ {I}を\ \ ]

  • メンテナンスサフィックス\(分\)の値のみを少しずつ、次に線分ツリーは、最初の半分を変更することができ、時間複雑度\(O(N \ログ\ n)を\)

  • この条件がないとスタック・セグメント・ツリーで前面から背面に増加単調性を維持することができます

  • 具体的には、各セグメントの間隔は、最小維持する\(MNの\)と間隔回答\(合計\)

  • かかわらず、現在のインターバルの\(K \)息子の周り\(L、R&LT \) 左息子\(Lの\)息子の周り\(L、Rの\)

    $ MN_ {R} \ LT MN_場合 {R} $、 右部分の寄与は、(mn_R \)を\再帰的に、直接回収し、(Lの\)\

    $ mn_R \ GE mn_rの$、add_Kレコード$の場合は(\によって表される)\ K \(右の息子の左息子がMNの答えを行く、直接統計\) add_K \(および再帰的に\)のR $

    時間複雑:$ O(n個の\ログ^ 2N)$

    #include<bits/stdc++.h>
    #define ll long long 
    #define ls (k<<1)
    #define rs (k<<1|1)
    
    using namespace std;
    
    char gc(){
      static char*p1,*p2,s[1000000];
      if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      return(p1==p2)?EOF:*p1++;
    }
    int rd(){
      int x=0;char c=gc();
      while(c<'0'||c>'9')c=gc();
      while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
      return x;
    }
    
    const int N=200010;
    int n,m,s[N];
    ll tmp,Mn,mn[N<<2],sum[N<<2],add[N<<2],ans;
    
    ll sg(int l,int r,int x){return ((r-l)&1)?0:l&1?-x:x;}
    void mfy(int k,int l){mn[k]=s[l];sum[k]=l&1?-s[l]:s[l];}
    void cal(int k,int l,int r){
      if(l==r){tmp+=sg(l,r,min(Mn,mn[k]));return;}
      int mid=(l+r)>>1;
      if(Mn<mn[rs])tmp+=sg(mid+1,r,Mn),cal(ls,l,mid);
      else tmp+=add[k],cal(rs,mid+1,r);
    }
    void pushup(int k,int l,int r){
      mn[k]=min(mn[ls],mn[rs]);
      int mid=(l+r)>>1; 
      tmp=0;Mn=mn[rs];
      cal(ls,l,mid);
      sum[k]=sum[rs]+(add[k]=tmp);
    }
    void build(int k,int l,int r){
      if(l==r){mfy(k,l);return;}
      int mid=(l+r)>>1;
      build(ls,l,mid);
      build(rs,mid+1,r);
      pushup(k,l,r);
    }
    void update(int k,int l,int r,int x){
      if(l==r){mfy(k,l);return;}
      int mid=(l+r)>>1;
      if(x<=mid)update(ls,l,mid,x);
      else update(rs,mid+1,r,x);
      pushup(k,l,r);
    }
    int main(){
      freopen("flip.in","r",stdin);
      freopen("flip.out","w",stdout);
      n=rd();
      for(int i=1;i<=n;++i){s[i]=rd();if(i&1)ans+=s[i];}
      build(1,2,n);
      printf("%lld\n",ans+sum[1]);
      m=rd();
      for(int i=1;i<=m;++i){
          int x=rd(),y=rd();
          if(x&1)ans-=s[x];
          s[x]-=y;if(x&1)ans+=s[x];
          if(x>1)update(1,2,n,x);
          printf("%lld\n",ans+sum[1]);
      }
      return 0;
    }

おすすめ

転載: www.cnblogs.com/Paul-Guderian/p/11051706.html