题目: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-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int maxK=; int N,K,M;
int a[maxN+];
int idx[maxN+];
int val[maxN+][maxK+];
int F[maxN+][maxK+];
int ans; #define lowbit(a) (a&(-a))
int tree[maxK+];
inline void update(int a){for(;a<=K;a+=lowbit(a))tree[a]++;}
inline int ask(int a){int res=;for(;a>=;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,,N)a[i]=gint();
re(i,,N)if(a[i]==-)idx[i]=++M;
mmst(tree,);re(i,,N)if(a[i]!=-)update(K-a[i]+);else re(j,,K) val[idx[i]][j]+=ask(K-j);
mmst(tree,);red(i,N,)if(a[i]!=-)update(a[i]); else re(j,,K)val[idx[i]][j]+=ask(j-);
re(j,,K)F[][j]=val[][j];
re(i,,M)
{
F[i][]=F[i-][]+val[i][];
re(j,,K) F[i][j]=min(F[i-][j],F[i][j-]-val[i][j-])+val[i][j];
}
ans=F[M][];re(j,,K)upmin(ans,F[M][j]);
mmst(tree,);re(i,,N)if(a[i]!=-){ans+=ask(K-a[i]);update(K-a[i]+);}
cout<<ans<<endl;
return ;
}

bzoj1786的更多相关文章

  1. [BZOJ1786][BZOJ1831]逆序对

    [BZOJ1786][BZOJ1831]逆序对 试题描述 输入 输出 输入示例 - - 输出示例 数据规模及约定 见“输入” 题解 首先这题有一个性质,即,填的数从左到右一定不降.证明不妨读者自己yy ...

  2. BZOJ1786 [Ahoi2008]Pair 配对 动态规划 逆序对

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1786 题意概括 给出长度为n的数列,只会出现1~k这些正整数.现在有些数写成了-1,这些-1可以变 ...

  3. 【BZOJ1786】[Ahoi2008]Pair 配对 DP

    [BZOJ1786][Ahoi2008]Pair 配对 Description Input Output Sample Input 5 4 4 2 -1 -1 3 Sample Output 4 题解 ...

  4. bzoj1831: [AHOI2008]逆序对(DP+双精bzoj1786)

    1831: [AHOI2008]逆序对 Description 小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之 ...

  5. BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对

    这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #inclu ...

  6. 【BZOJ1786】[Ahoi2008]Pair 配对

    题解: 打表出奇迹 能发现所有ai一定是不减的 其实很好证明啊.. 考虑两个位置x y(y在x右边) x的最优值已经知道了 考虑y处 先让y=x,然后开始变化 因为x处已经是最优的了,所以如果减小,那 ...

  7. 洛谷 P4280 bzoj1786 [AHOI2008]逆序对(dp)

    题面 luogu bzoj 题目大意: 给你一个长度为\(n\)的序列,元素都在\(1-k\)之间,有些是\(-1\),让你把\(-1\)也变成\(1-k\)之间的数,使得逆序对最多,求逆序对最少是多 ...

  8. bzoj1786: [Ahoi2008]Pair 配对&&1831: [AHOI2008]逆序对

    一个自以为很对的东西,我们往-1放的数肯定是不增的. 然后就预处理一下,假如i这个位置放j会多多少逆序对. DP一下,我的复杂度应该是O(n*m^2)的,然而你随便搞都能省掉一个m吧,我算了算好像可以 ...

随机推荐

  1. 使用Horner法则计算多项式的值

    计算Pn(x) = an * x^n + an-1 * x^(n-1) + ... + a1 * x + a0 直接计算,需要做的乘法次数 1+2+3+……+n = n(1+n)/2 = O(n2) ...

  2. zookeeper[6] zookeeper FAQ(转)

    转自:http://www.cnblogs.com/zhengran/p/4601855.html 1. 如何处理CONNECTION_LOSS?在Zookeeper中,服务器和客户端之间维持一个长连 ...

  3. JAVA并发七(多线程环境中安全使用集合API)

    在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对 ...

  4. (转)利用ant在Mac 下自动化打包签名Android程序

    1.创建一个android项目 参数说明:-k /--package 为命名空间(包名)-a /--name 工程名-p /--path 项目 -t 为目标平台的版本编号 命令:./android c ...

  5. Redis环境搭建(Linux)

    1.简介       redis是一个开源的key-value数据库.它又经常被认为是一个数据结构服务器.因为它的value不仅包括基本的string类型还有 list,set ,sorted set ...

  6. HDU 5067-Harry And Dig Machine(DFS)

    Harry And Dig Machine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  7. C++ Win32控制台应用程序捕捉关闭事件

      #include#includebool ctrlhandler( DWORD fdwctrltype ){    switch( fdwctrltype )    {    // handle ...

  8. VMware Virtual Machine安装报错解决1

    安装完VMware virtual machine 后,再进行 "create a new virtual machine"最后点击"Finish"时,报如下错 ...

  9. C#。5 结构体

    结构体:相当于是我们自己定义的一种复杂的类型. 常见简单类型:int...  double float bool char string 常见复杂类型:DateTime  数组类型 生活中大部份的对象 ...

  10. js获取页面名称

    function pageName() {    var strUrl = location.href;    var arrUrl = strUrl.split("/");    ...