bzoj1786
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1786
刚看上去觉得挺吓人的。。。。。。
冥冥之中我的内心深处告诉我填进去的数一定是非严格递增的。
结果真的是这样:
对于两个相邻的未填数字x和y,不管我们怎么交换x和y,影响的只是红色框里面的,我们把红色框单独取出来。
不妨设x<y。
我们把红色框里面的数拍一下序(因为有可能有多个x和y,所以写多了几个,不影响结果)
如果x和y不交换,那么逆序对个数为红色线覆盖的个数
如果x和y交换,那么逆序对个为蓝色线覆盖的个数+1
很明显很明显不交换比交换优
所以填进去的数一定是非严格递增的。
知道的了这个,就很简单了,求出val[i][j],表示第i个空位填j的时候会产生多少个逆序对,这个可以用树状数组解决。
然后就继续求解。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxN=10000; const int maxK=100; int N,K,M; int a[maxN+100]; int idx[maxN+100]; int val[maxN+100][maxK+100]; int F[maxN+100][maxK+100]; int ans; #define lowbit(a) (a&(-a)) int tree[maxK+100]; inline void update(int a){for(;a<=K;a+=lowbit(a))tree[a]++;} inline int ask(int a){int res=0;for(;a>=1;a-=lowbit(a))res+=tree[a];return res;} int main() { freopen("bzoj1786.in","r",stdin); freopen("bzoj1786.out","w",stdout); int i,j; N=gint();K=gint(); re(i,1,N)a[i]=gint(); re(i,1,N)if(a[i]==-1)idx[i]=++M; mmst(tree,0);re(i,1,N)if(a[i]!=-1)update(K-a[i]+1);else re(j,1,K) val[idx[i]][j]+=ask(K-j); mmst(tree,0);red(i,N,1)if(a[i]!=-1)update(a[i]); else re(j,1,K)val[idx[i]][j]+=ask(j-1); re(j,1,K)F[1][j]=val[1][j]; re(i,2,M) { F[i][1]=F[i-1][1]+val[i][1]; re(j,2,K) F[i][j]=min(F[i-1][j],F[i][j-1]-val[i][j-1])+val[i][j]; } ans=F[M][1];re(j,2,K)upmin(ans,F[M][j]); mmst(tree,0);re(i,1,N)if(a[i]!=-1){ans+=ask(K-a[i]);update(K-a[i]+1);} cout<<ans<<endl; return 0; }