题意:N个数,按顺序划分为K组,使得逆序对之和最小。

思路:之前能用四边形不等式写的,一般网上都还有DP单调性分治的做法,今天也尝试用后者写(抄)了一遍。即:

分成K组,我们进行K-1次分治,get(l,r,L,R)中如果mid位置的最优解来自MID,那么分别以mid和MID和分界线,有get(l,mid-1,L,MID);get(mid+1,r,MID,R);

区间逆序对没有什么特别高效的方法,我们用莫对跑ok了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int a[maxn],sum[maxn],dp[maxn],ans[maxn],N,K,ql,qr,cost;
inline int query(int x){int res=;while(x){ res+=sum[x]; x-=(-x)&x;} return res;}
inline void add(int x,int val){while(x<=N){ sum[x]+=val; x+=(-x)&x;} }
inline void move(int l,int r)
{
while(ql>l) cost+=query(a[--ql]-),add(a[ql],);
while(qr<r) cost+=query(N)-query(a[++qr]),add(a[qr],);
while(ql<l) add(a[ql],-),cost-=query(a[ql++]-);
while(qr>r) add(a[qr],-),cost-=query(N)-query(a[qr--]);
}
inline void get(int l,int r,int L,int R)
{
if(l>r) return ;
int mid=(l+r)>>,Mid;
for(int i=min(R+,mid);i>L;i--){
move(i,mid);
if(dp[i-]+cost<ans[mid]) {ans[mid]=dp[i-]+cost; Mid=i-;}
}
get(l,mid-,L,Mid); get(mid+,r,Mid,R);
}
int main()
{
scanf("%d%d",&N,&K);
rep(i,,N) scanf("%d",&a[i]);
rep(i,,N) ans[i]=ans[i-]+query(N)-query(a[i]),add(a[i],);
ql=; qr=N; cost=ans[N];
rep(i,,K){
memcpy(dp,ans,sizeof(ans)); //把上一轮的结果复制
memset(ans,0x3f,sizeof(ans));
get(,N,,N-);
}
printf("%d\n",ans[N]);
return ;
}

我也写了四边形不等式来优化DP,其他部分一样。 然而T了,估计是莫对跑得太多了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int a[maxn],sum[maxn],dp[maxn][],pos[maxn][],N,K,ql,qr,cost;
inline int query(int x){int res=;while(x){ res+=sum[x]; x-=(-x)&x;} return res;}
inline void add(int x,int val){while(x<=N){ sum[x]+=val; x+=(-x)&x;} }
inline void move(int l,int r)
{
while(ql>l) cost+=query(a[--ql]-),add(a[ql],);
while(qr<r) cost+=query(N)-query(a[++qr]),add(a[qr],);
while(ql<l) add(a[ql],-),cost-=query(a[ql++]-);
while(qr>r) add(a[qr],-),cost-=query(N)-query(a[qr--]);
}
int main()
{
scanf("%d%d",&N,&K);
rep(i,,N) scanf("%d",&a[i]);
memset(dp,0x3f,sizeof(dp)); dp[][]=;
rep(i,,N) dp[i][]=dp[i-][]+query(N)-query(a[i]),add(a[i],);
ql=; qr=N; cost=dp[N][];
rep(i,,K){
rep(j,,N){
int L=pos[j][i-]?pos[j][i-]:;
int R=pos[j+][i]?pos[j+][i]:N-;
rep(k,L,R) {
if(k>=j) continue;
move(k+,j);
if(dp[j][i]>dp[k][i-]+cost){
dp[j][i]=dp[k][i-]+cost;
pos[j][i]=k;
}
}
}
}
printf("%d\n",dp[N][K]);
return ;
}

BZOJ5125: [Lydsy1712月赛]小Q的书架(DP决策单调性)的更多相关文章

  1. BZOJ5125: [Lydsy1712月赛]小Q的书架【决策单调性优化DP】【BIT】【莫队】【分治】

    小Q有n本书,每本书有一个独一无二的编号,现在它们正零乱地在地上排成了一排. 小Q希望把这一排书分成恰好k段,使得每段至少有一本书,然后把每段按照现在的顺序依次放到k层书架的每一层上去.将所有书都放到 ...

  2. bzoj 5125: [Lydsy1712月赛]小Q的书架

    新学了一波 决策单调性 dp 套路.... 这种dp一般是长这样的 => f[i][j] = max/min  { f[i-1][k] + cost(k+1,j)} ,其中cost函数满足四边形 ...

  3. BZOJ5125 小Q的书架(决策单调性+动态规划+分治+树状数组)

    设f[i][j]为前i个划成j段的最小代价,枚举上个划分点转移.容易想到这个dp有决策单调性,感性证明一下比较显然.如果用单调栈维护决策就不太能快速的求出逆序对个数了,改为使用分治,移动端点时树状数组 ...

  4. [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)

    显然有决策单调性,但由于逆序对不容易计算,考虑分治DP. solve(k,x,y,l,r)表示当前需要选k段,待更新的位置为[l,r],这些位置的可能决策点区间为[x,y].暴力计算出(l+r)/2的 ...

  5. 【BZOJ 5125】小Q的书架

    Problem Description 小 \(Q\) 有 \(n\) 本书,每本书有一个独一无二的编号,现在它们正零乱地在地上排成了一排. 小 \(Q\) 希望把这一排书分成恰好 \(k\) 段,使 ...

  6. 【BZOJ5073】[Lydsy十月月赛]小A的咒语 DP(错解)

    [BZOJ5073][Lydsy十月月赛]小A的咒语 题解:沙茶DP,完全不用后缀数组. 用f[i][j]表示用了A的前i个字符,用了j段,最远能匹配到哪.因为显然我们能匹配到的地方越远越好,所以我们 ...

  7. [BZOJ4813][CQOI2017]小Q的棋盘(DP,贪心)

    4813: [Cqoi2017]小Q的棋盘 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 804  Solved: 441[Submit][Statu ...

  8. [NOI2009]诗人小G --- DP + 决策单调性

    [NOI2009]诗人小G 题目描述: 小G是一个出色的诗人,经常作诗自娱自乐. 但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并 ...

  9. [NOI2009]诗人小G(dp + 决策单调性优化)

    题意 有一个长度为 \(n\) 的序列 \(A\) 和常数 \(L, P\) ,你需要将它分成若干段,每 \(P\) 一段的代价为 \(| \sum ( A_i ) − L|^P\) ,求最小代价的划 ...

随机推荐

  1. 【cs231n】线性分类笔记

    前言 首先声明,以下内容绝大部分转自知乎智能单元,他们将官方学习笔记进行了很专业的翻译,在此我会直接copy他们翻译的笔记,有些地方会用红字写自己的笔记,本文只是作为自己的学习笔记.本文内容官网链接: ...

  2. docker 集群 笔记

    docker 集群 Docker 容器 移除所有的容器和镜像(大扫除) 用一行命令大扫除: docker kill $(docker ps -q) ; docker rm $(docker ps -a ...

  3. python collections deque

    collections是python的高级容器类库,包含了dict.truple之外的常用容器. 下面介绍常用的deque 1. deque是双端队列,可以从两端塞元素进去,也可以从两端取元素. 2. ...

  4. oracle快速创建主键

    oracle中,有时我们会发现有一些表中,一些记录它们每个字段的数据 都是一样一样的,即重复数据,这种数据的不存在肯定是不对了. 究其原因,就是该表没有主键,给一个表创建主键,非常容易: alter ...

  5. android ui界面设计参数讲解

    百度文库: http://wenku.baidu.com/link?url=s66Hw6byBEzmjL77doYL1YQN4Y_39F7MovaHKs5mVGrzTDOQCAmiM-1N_6Cdm- ...

  6. windows向github提交代码

    随便写的,留给自己看. 一.在github上注册并建立自己的仓库http://www.cnblogs.com/keZhenxu94/p/5288488.html 二.安装windows版本git界面工 ...

  7. spark 性能优化

    1.内存 spark.storage.memoryFraction:很明显,是指spark缓存的大小,默认比例0.6 spark.shuffle.memoryFraction:管理executor中R ...

  8. 《OpenCL编程指南》之 与Direct3D互操作

    介绍OpenCL与D3D 10之间的互操作. 1.初始化OpenCL上下文实现Direct3D互操作 OpenCL共享由pragma cl_khr_d3d10_sharing启用: #pragma O ...

  9. 005-对象——对象的 final const

    <?php /** * */ /*class shouji { public $pinpai; final function chongdian() { //final 最终的 return $ ...

  10. JBPM4入门——2.在eclipse中安装绘制jbpm流程图的插件

    本博文只是简要对JBPM4进行介绍,如需更详细内容请自行google 链接: JBPM入门系列文章: JBPM4入门——1.jbpm简要介绍 JBPM4入门——2.在eclipse中安装绘制jbpm流 ...