bzoj1831 逆序对 (dp+树状数组)

注意到,所有的-1应该是一个不降的序列,否则不会更优
那就先求出来不是-1的的逆序对个数,然后设f[i][j]表示第i个-1放成j的前i个-1带来的最小逆序对数量
这个可以树状数组来求

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e4+10,maxk=110;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 
16 int f[maxn][maxk],tr[maxn],a[maxn],b[maxn],N,K,M;
17 
18 inline int lowbit(int x){return x&(-x);}
19 inline void add(int x,int y){
20     for(;x<=K;x+=lowbit(x)) tr[x]+=y;
21 }
22 inline int query(int x){
23     int re=0;for(;x;x-=lowbit(x)) re+=tr[x];return re;
24 }
25 
26 int main(){
27     //freopen("","r",stdin);
28     int i,j,k;
29     N=rd(),M=0,K=rd();
30     int ans=0;
31     for(i=1;i<=N;i++){
32         a[i]=rd();
33         if(a[i]==-1) b[++M]=i;
34         else{
35             ans+=query(K)-query(a[i]);
36             add(a[i],1);
37         }
38     }
39     CLR(tr,0);
40     for(i=1,j=1;i<=M;i++){
41         for(;j<=b[i];j++){
42             if(a[j]!=-1) add(a[j],1);
43         }
44         for(k=1;k<=K;k++)
45             f[i][k]+=query(K)-query(k);
46     }
47     CLR(tr,0);
48     for(i=M,j=N;i;i--){
49         for(;j>=b[i];j--){
50             if(a[j]!=-1) add(a[j],1);
51         }
52         for(k=1;k<=K;k++)
53             f[i][k]+=query(k-1);
54     }
55     for(i=1;i<=M+1;i++){
56         for(j=1;j<=K;j++){
57             int mi=1e9;
58             for(k=1;k<=j;k++){
59                 mi=min(mi,f[i-1][k]);
60             }
61             f[i][j]+=mi;
62         }
63     }
64     printf("%d\n",f[M+1][K]+ans);
65     return 0;
66 }

 

posted @ 2018-10-29 21:07  Ressed  阅读(202)  评论(0编辑  收藏  举报