[BZOJ5125] bookshelf small Q (decision monotony of divide and conquer DP + + + Mo Fenwick tree team?)

\ (O (n ^ 2k) \) Comparative miss

\(dp[i][j]=\min\limits_{k<i}(dp[k][j-1]+w(k+1,i))\)

\ (W \) is the number of reverse order.

Play table found in the decision-making monotonic.

But we can not find reverse quickly count the number of so monotonous queue not working.

Consider divide and conquer,

\ (solve (l, r, L, R, k) \) represents to calculate the portion of \ ([L, R & lt] \) , may decision point is located in \ ([L, R] \ ) inside, so violent calculated \ (mid \) is the optimal decision point \ (the p-\) , on both sides of recursion dp

/*
@Date    : 2019-08-16 21:14:43
@Author  : Adscn ([email protected])
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define int long long
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
IL int getint()
{
    RG int xi=0;
    RG char ch=gc;
    bool f=0;
    while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10,0);
    putchar(k%10+'0');
    if(ch)putchar(ch);
}
const int N=4e4+7;
int n,K,sum;
int c[N],a[N],f[N][11];
void add(int k,int x){for(;k<=n;k+=k&-k)c[k]+=x;}
int qry(int x){int ans=0;for(;x;x-=x&-x)ans+=c[x];return ans;}
int L,R;
void move(int l,int r){
    while(L<l)sum-=qry(a[L]-1),add(a[L++],-1);
    while(L>l)sum+=qry(a[L-1]-1),add(a[--L],1);
    while(R<r)sum+=R-L+1-qry(a[R+1]),add(a[++R],1);
    while(R>r)sum-=R-L+1-qry(a[R]),add(a[R--],-1);
}
void solve(int l,int r,int L,int R,int now)
{
    if(l>r)return;
    int mid=(l+r)>>1,p=L;
    for(int i=L;i<=min(mid-1,R);++i)
    {
        move(i+1,mid);
        if(f[i][now-1]+sum<f[mid][now])f[mid][now]=f[i][now-1]+sum,p=i;
    }
    solve(l,mid-1,L,p,now);
    solve(mid+1,r,p,R,now);
}
signed main(void)
{
    n=gi,K=gi;
    for(int i=1;i<=n;++i)a[i]=gi;
    memset(f,127,sizeof f);
    L=1,R=0;
    for(int i=1;i<=n;++i)move(1,i),f[i][1]=sum;
    for(int i=2;i<=K;++i)solve(1,n,1,n,i);
    pi(f[n][K]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/LLCSBlog/p/11366472.html