BZOJ5125: [Lydsy1712月赛]小Q的书架(DP决策单调性)
题意: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决策单调性)的更多相关文章
- BZOJ5125: [Lydsy1712月赛]小Q的书架【决策单调性优化DP】【BIT】【莫队】【分治】
小Q有n本书,每本书有一个独一无二的编号,现在它们正零乱地在地上排成了一排. 小Q希望把这一排书分成恰好k段,使得每段至少有一本书,然后把每段按照现在的顺序依次放到k层书架的每一层上去.将所有书都放到 ...
- bzoj 5125: [Lydsy1712月赛]小Q的书架
新学了一波 决策单调性 dp 套路.... 这种dp一般是长这样的 => f[i][j] = max/min { f[i-1][k] + cost(k+1,j)} ,其中cost函数满足四边形 ...
- BZOJ5125 小Q的书架(决策单调性+动态规划+分治+树状数组)
设f[i][j]为前i个划成j段的最小代价,枚举上个划分点转移.容易想到这个dp有决策单调性,感性证明一下比较显然.如果用单调栈维护决策就不太能快速的求出逆序对个数了,改为使用分治,移动端点时树状数组 ...
- [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
显然有决策单调性,但由于逆序对不容易计算,考虑分治DP. solve(k,x,y,l,r)表示当前需要选k段,待更新的位置为[l,r],这些位置的可能决策点区间为[x,y].暴力计算出(l+r)/2的 ...
- 【BZOJ 5125】小Q的书架
Problem Description 小 \(Q\) 有 \(n\) 本书,每本书有一个独一无二的编号,现在它们正零乱地在地上排成了一排. 小 \(Q\) 希望把这一排书分成恰好 \(k\) 段,使 ...
- 【BZOJ5073】[Lydsy十月月赛]小A的咒语 DP(错解)
[BZOJ5073][Lydsy十月月赛]小A的咒语 题解:沙茶DP,完全不用后缀数组. 用f[i][j]表示用了A的前i个字符,用了j段,最远能匹配到哪.因为显然我们能匹配到的地方越远越好,所以我们 ...
- [BZOJ4813][CQOI2017]小Q的棋盘(DP,贪心)
4813: [Cqoi2017]小Q的棋盘 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 804 Solved: 441[Submit][Statu ...
- [NOI2009]诗人小G --- DP + 决策单调性
[NOI2009]诗人小G 题目描述: 小G是一个出色的诗人,经常作诗自娱自乐. 但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并 ...
- [NOI2009]诗人小G(dp + 决策单调性优化)
题意 有一个长度为 \(n\) 的序列 \(A\) 和常数 \(L, P\) ,你需要将它分成若干段,每 \(P\) 一段的代价为 \(| \sum ( A_i ) − L|^P\) ,求最小代价的划 ...
随机推荐
- apt get update无法正常使用解决方案(转载)
apt get update无法正常使用 解决方法参考博客 [问题描述] 前几天执行apt相关命令(如apt-get update),都会长时间停在``等待报头'',超时后,显示连接超时. 换了快速指 ...
- codeforce diversity
2017-08-25 14:59:34 writer:pprp 题意如下:给你一个串字符,再给你一个数字,表示在字符串中的各不相同的字符个数, 问你最少需要改变几个字符达到要求,不能达到要求就输出im ...
- Jenkins Pipeline shell脚本用svn_revision当做系统版本号
1. 使用dir命令,进入发布目录,版本号所在文件夹. 2. 使用sed命令 修改替换版本号,这里使用vvvv作为要替换的版本号. 3. 最后一步可以不加.只是方便查看效果. stage(" ...
- 【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍
写在前面 牢牢占据容器技术统治地位的 Kubernetes,其重要性想必不言而喻,我保证本文是最详尽的 Kubernetes 技术文档,从我在后台排版了这么漫长的时间就能看出来.废话不多说 — — 以 ...
- webBrowser.DocumentText重新赋值无效解决方法
因为webBrowser这个控件的webBrowser.DocumentText是异步的,所以要自己调用刷新: webBrowser.Navigate("about:blank") ...
- 设计模式--命令模式C++实现
命令模式C++实现 1定义 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求队列或者记录请求日志,可以提供命令的撤销和恢复功能 2类图 角色描述: Receiver接受者角色,就 ...
- 【转载】deque双向队列
继vector和queue之后,又发现一个很好用的东西. 本篇转载自http://blog.csdn.net/morewindows/article/details/6946811 deque双向队列 ...
- JavaScript中Function Declaration与Function Expression 或者说 function fn(){}和var fn=function(){} 的区别
JavaScript是一种解释型语言,函数声明会在JavaScript代码加载后.执行前被解释,而函数表达式只有在执行到这一行代码时才会被解释. 在JS中有两种定义函数的方式, 1是:var aaa= ...
- MySQL索引优化详解
MySQL存储引擎简介 查看命令 a. 查看所使用的MySQL现在已提供什么存储引擎: mysql> show engines; b. 查看所使用的MySQL当前默认的存储引擎: mysql&g ...
- 010PHP基础知识——运算符(三)
<?php /** * 位运算符: * 1:&按位与:左右两边的数,同位都为1,返回是1,否则返回是0 */ /*$a = 5; $b = 6; $a = decbin($a);//10 ...