オンライントレーニング・シーケンス[19]
(http://zhengruioi.com/problem/1150)
ソル:
フェンウィックツリーの最適化\(DP \)は、暴力からしばしばです\(DP \)インスピレーションを得ました。考えてみましょう\(O(N ^ 2) \) 各点の列挙を変更しようとする元のシーケンスのコストが計算されている限り、暴力を、そして、我々はオリジナルシリーズの数にその番号を修正する必要があることは明らかな性質がある登場。あなたは3例の合計を見つけるだろう、最適化を考えてみましょう:(今置くと仮定(P_I \)\となり\(p_j \)、\ (nxt_i \)を表す\(P_Iを\)場所次の発生、それが設定されていない場合です\(。N- + 1 \) )
。1、\(J <I \) 、時間の変更は、後者の寄与には影響しません限り、(I \)\フロント検索P_I-p_jは| \( | \)最小は、使用を検討することができます\(セット\)のメンテナンスを。
2、\(I <J <nxt_i \) 、手でプレーをしてい\ \([J、nxt_i) )この段落番号があまり頻繁に現れる\(1 \)この状況は良く発生する可能性があることを意味し、ソリューション。このとき、のための新しい価格\(| a_iを-a_j | -S(J)+ S(nxt_i)\) 、前記\(S(K)= \ ^ {N-SUM _} {K} IはI \を=)。その後、我々は論じ2例の絶対値を開けなければならない:
I.を\(a_iを> a_j \)、\ (ANS = \分\ {a_iを+ S(nxt_i)-a_j-S(J)\} \) 、その後、私たちは長いフェンウィックツリーのメンテナンスなどとして見つけた\( - a_j-S(J )\) ライン上の最小値は、クエリが唯一チャビーに注意することができます\(a_iを\)が小さいです。
II。\(a_iを<a_j \)、\ (ANS = \分\ { - a_iを+ S(nxt_i)a_j + -S(J)\} \)ツリーメンテナンスアレイと、\(a_j-S(J )\)最小クエリ共感。
3、\(nxt_i <J \) 、手でプレイし続けるで見つかった\ \([nxt_i、j)は ) この段落番号がより頻繁に表示される(1 \)\、その後、状況はよりよい解決策が現れることはできません直接廃棄されました。
総複雑\(O(N \ Nログ
)\) Tucao:この分類は、高い数学をやってような感じをしている方法について説明しますか?(そして爆発ゼロの間違い)
const int N=500005;
int n,p[N],tmp[N],q[N],nxt[N],h[N];
ll ans,as;
struct bit{
ll st[N];
inline int lowbit(int x){return x&-x;}
inline void inst(int x,ll y){while(x) st[x]=min(st[x],y),x-=lowbit(x);}
inline ll query(int x){ll res=1e18;while(x<=n) res=min(res,st[x]),x+=lowbit(x);return res;}
} t1,t2;
inline ll calc(int x){return 1ll*(n-x+1)*(n+x)/2;}
set<int> s;
set<int>::iterator it;
int main(){
read(n);
for(int i=1;i<=n;i++) read(p[i]),tmp[i]=p[i];
sort(tmp+1,tmp+1+n);
int k=unique(tmp+1,tmp+1+n)-tmp-1;
for(int i=1;i<=n;i++) q[i]=lower_bound(tmp+1,tmp+1+k,p[i])-tmp;
for(int i=1;i<=n;i++){
if(h[q[i]]) nxt[h[q[i]]]=i;
h[q[i]]=i;
}
for(int i=1;i<=n;i++){
if(h[q[i]]) nxt[h[q[i]]]=n+1;
h[q[i]]=0;
}
int num=0;
for(int i=1;i<=n;i++){
if(!h[q[i]]) h[q[i]]=1,num++;
ans+=1ll*num*i;
}as=ans;
memset(h,0,sizeof(h));
for(int i=1;i<=n;i++){
if(h[q[i]]) continue;
h[q[i]]=i;ll val=calc(i)-calc(nxt[i]);
it=s.lower_bound(p[i]);
if(it!=s.end()) ans=min(ans,as-val+*it-p[i]);
if(it!=s.begin()) ans=min(ans,as-val+p[i]-*(--it));
s.insert(p[i]);
}
memset(t1.st,0x3f,sizeof(t1.st));
memset(t2.st,0x3f,sizeof(t2.st));
for(int i=n;i>0;i--){
if(h[q[i]]!=i) continue;
ans=min(ans,as+t1.query(n-q[i]+1)+calc(nxt[i])+p[i]);
ans=min(ans,as+t2.query(q[i])+calc(nxt[i])-p[i]);
t1.inst(n-q[i]+1,-calc(i)-p[i]);
t2.inst(q[i],-calc(i)+p[i]);
}
print(ans);
return 0;
}