タイトル
小さな\(\)と小\(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; }