問題の意味
列の数に\(P_1、P_2、...、P_N \) 、および変更するには、それぞれの変更が必要とした後、答え:
元単調に形成された列数の順位非減少\(A_1、A_2、...、 A_N \) 計算
\ [\ FRAC {\ sum_ { {iは時間\ a_j 1} ^ {N-1} \ sum_ {J = + 1} ^ {n}はa_iを\回= 2 ^ {N + IJ-1}} } ^ N-2 \]。
問題の解決策
\(\ sum_は、{I 1 =回2 ^ {N + IJ-1} \ a_j sum_ {J = + 1} ^ {n}はa_iを\回\ ^ {N-1}} \) セグメントツリーであってもよいです計算。
セット管理の間隔\([L、R] \ ) ノードである(I \)\、提供:
\(ヴァル[I] \)複数の列\(a_l、A_ {L + 1}、...、A_R \)の合計値
\(SUML [I] + = A_L A_ {L} +。1つの\ 2 + ... + A_Rタイムズ\ RLタイムズ2 ^ {} \)である
\(SumR [I]は= A_L \ ^ 2回R1は。A_ {} + {L} + 1 \タイムズ^ {2} 1-RL)は、+ ... + \ A_Rある
(\ SIZ [I] \)の\(a_l、A_ {L + 1}、... A_R \)の非零要素の数は、
配置(LS \)\の\(I \)左の子\(RS \)の\(I \)右息子、次いで:
\(ヴァル[I] =ヴァル[LS] \タイムズ2 ^ {SIZ [RS]} + SUML [LS] \タイムズSumR [RS] +ヴァル[RS] \タイムズ2 ^ {SIZ [LS]} \)
\(SUML [I] = SUML [ LS] + suml [RS] \回2 ^ {SIZ [LS]} \)
\(sumr [I] = sumr
[LS] \回2 ^ {SIZ [RS]} + sumr [RS] \) このセグメントツリーメンテナンス、我々は、任意のノードへの変更、および根を容易に行うことができるヴァル(\ \ )答えです。
この質問は、オリジナルを作るために、列の数を計算する前に、トラブルの少しですが、それは、列のと障害の切除後の番号と思われます。
実際には、列の数を増加して、セグメントツリーの維持を保証するように、初期値が最初であってもよく、すべての変更は、各操作は、ツリー行のノードに対応し、ソーティング次いで抑え、かつれます。
あなたが位置の値を変更したい場合は、最初の位置、元のツリー改行の数に対応することができます\(0 \) 、および現在位置の値に対応する番号を変更します。
コード
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define ff first
#define ss second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=3e5+10;
const int mod=1e9+7;
int n,q,idx[N],pos[N*2],now[N*2];
PII p[2*N];
LL po[2*N];
LL qpow(LL x,LL k){
LL res=1;
while(k){
if(k&1) res=res*x%mod;
k>>=1;x=x*x%mod;
}
return res;
}
struct SegTree{
#define mid ((l+r)>>1)
LL val[N*8],suml[N*8],sumr[N*8],siz[N*8];
void upd(int id,int l,int r,int pos,int x){
if(l==r) {val[id]=0;suml[id]=sumr[id]=x;siz[id]=(bool)x;return;}
if(pos<=mid) upd(id<<1,l,mid,pos,x);
else upd(id<<1|1,mid+1,r,pos,x);
val[id]=(val[id<<1]*po[siz[id<<1|1]]%mod+suml[id<<1]*sumr[id<<1|1]+val[id<<1|1]*po[siz[id<<1]]%mod)%mod;
suml[id]=(suml[id<<1]+suml[id<<1|1]*po[siz[id<<1]])%mod;
sumr[id]=(sumr[id<<1]*po[siz[id<<1|1]]+sumr[id<<1|1])%mod;
siz[id]=siz[id<<1]+siz[id<<1|1];
}
#undef mid
}tr;
int main(){
scanf("%d",&n);
po[0]=1;
for(int i=1;i<=n;i++) po[i]=po[i-1]*2%mod;
for(int i=1;i<=n;i++) scanf("%lld",&p[i].ff),p[i].ss=i;
scanf("%d",&q);
for(int i=1;i<=q;i++) scanf("%d%d",&idx[i],&p[i+n].ff),p[i+n].ss=i+n;
sort(p+1,p+n+q+1);
for(int i=1;i<=n+q;i++) pos[p[i].ss]=i;
LL inv=qpow(po[n],mod-2);
for(int i=1;i<=n+q;i++) if(p[i].ss<=n) {
now[p[i].ss]=pos[p[i].ss];
tr.upd(1,1,n+q,i,p[i].ff);
}
printf("%lld\n",tr.val[1]*inv%mod);
for(int i=1;i<=q;i++){
tr.upd(1,1,n+q,now[idx[i]],0);
tr.upd(1,1,n+q,pos[n+i],p[pos[n+i]].ff);
now[idx[i]]=pos[n+i];
printf("%lld\n",tr.val[1]*inv%mod);
}
return 0;
}