질문 펜윅 트리의 일부

온라인 교육 순서 [19]

( http://zhengruioi.com/problem/1150 )

솔:

펜윅 트리 최적화 \ (DP \) 폭력에서 자주 \ (DP는 \) 영감을. 고려 \ (O (N ^ 2) \) 각 지점의 열거를 수정하려고 다음 원래 시퀀스의 비용을 계산 한, 폭력, 그리고 우리가 원래 시리즈의 번호로 해당 번호를 수정해야한다는 분명한 성격이 나타났다. 최적화를 고려, 세 가지 경우 총은 이제 넣어 가정 해 :( 찾을 수 있습니다 (p_i \) \ 된다 (p_j \) \ , \ (nxt_i는 \) 대표 \ (p_i \) 가 설정되지 않은 경우 위치 다음에 나타나는, 이다 \ (. N- + 1 \) )
. (1), \ (J <I \) , 시간 변경, 후자의 기여에 영향을 미치지 않습니다 너무 오래 같은 (I \) \ 전면 발견 p_i-p_j는 | \ ( | \) 최소 사용하여 고려 될 수있다 \ (세트 \) 유지 보수.
2 \ (나는 <J는 <nxt_i \) , 손으로 플레이 검색된 \ ([J, nxt_i) \ ) 이 단락 번호가 적게 나타나는 \ (1 \) , 이는 이러한 상황이 잘 일어날 수 있다는 것을 의미 솔루션입니다. 이때,위한 새로운 가격 \ (| A_I-a_j | -S (J) + S (nxt_i) \) , 상기\ (S (K) = \ ^ {N-SUM은 _} {K}는 I는 \ = I) . 다음 우리는 두 경우의 절대 값이 논의 열어야 :
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;
}


추천

출처www.cnblogs.com/zxynothing/p/11838832.html