bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=2726
【题意】
将n个任务划分成若干个块,每一组Mi任务花费代价(T+sigma{ tj }+s)*sima{ fi },j属于Mi,T为当前时间,问最小代价。
【思路】
设f[i]为将前i个任务划分完成的最小费用,Ti Fi分别表示t和f的前缀和,则不难写出转移方程式:
f[i]=min{ f[j]+(F[n]-F[j])*(T[i]-T[j]+s) },1<=j<=i-1
经过整理得到:
f[i]=min{ -T[i]*F[j]+(f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j]) }
设X(i)=F[i],Y(i)=f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j],a(i)=T[i]则有:
f[i]=min{ -a(i)*X(j)+Y(j) }
则我们需要:
min p = -a(i)*X(j)+Y(j)
即最小化直线方程:Y(j)=a(i)*X(j)+p的截距。
如果时间没有负数的话(出题人神脑洞<_<,这个题可以直接上单调队列维护下凸线。事实上这个算法可以得到60分。
有了负数以后因为斜率不满足随x单调,所以不能使用单调队列。
然后这道题就需要用splay或CDQ分治解。
Splay写法还是不会=-=,CDQ分治的处理和 这道题 类似,就不再赘述了。
需要注意的:x,y可能到达long long级别,所以不要直接除得slop
运算过程中long long的标识。
归并数组的时候几个小条件。
【代码】
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
#define rep(a,b,c) for(int a=(b);a>=(c);a--)
using namespace std; typedef long long ll;
const int N = 5e5+;
const ll inf = 1e18; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Pt
{
ll x,y,k;
int id;
bool operator < (const Pt& rhs) const
{
return k<rhs.k;
}
}q[N],t[N]; bool cmp(const Pt& a,const Pt& b)
{
return a.x<b.x || a.x==b.x&&a.y<b.y;
} int T[N],F[N],st[N],top,n,s; ll f[N]; ll U(int j,int k)
{
return (ll)q[k].y-q[j].y;
}
ll D(int j,int k)
{
return (ll)q[k].x-q[j].x;
} void solve(int l,int r)
{
if(l==r) {
q[l].x=(ll)F[l];
q[l].y=(ll)f[l]-(ll)F[n]*T[l]+(ll)F[l]*T[l]-(ll)s*F[l];
return ;
}
int mid=l+r>>;
int l1=l,l2=mid+;
FOR(i,l,r) {
if(q[i].id>mid) t[l2++]=q[i];
else t[l1++]=q[i];
}
memcpy(q+l,t+l,sizeof(Pt)*(r-l+));
solve(l,mid);
top=;
FOR(i,l,mid) {
while(top> && (ll)U(st[top-],st[top])*D(st[top-],i)>(ll)U(st[top-],i)*D(st[top-],st[top])) top--;
st[++top]=i;
}
int j=;
FOR(i,mid+,r) {
while(j<top && U(st[j],st[j+])<(ll)q[i].k*D(st[j],st[j+])) j++;
f[q[i].id]=min(f[q[i].id],-(ll)q[i].k*q[st[j]].x+q[st[j]].y+(ll)F[n]*(T[q[i].id]+s));
}
solve(mid+,r);
l1=l,l2=mid+;
FOR(i,l,r) {
if((l2>r||cmp(q[l1],q[l2]))&&l1<=mid) t[i]=q[l1++];
else t[i]=q[l2++];
}
memcpy(q+l,t+l,sizeof(Pt)*(r-l+));
} int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
n=read(),s=read();
FOR(i,,n)
T[i]=read(),T[i]+=T[i-],
F[i]=read(),F[i]+=F[i-];
FOR(i,,n) {
q[i].id=i;
q[i].k=T[i];
f[i]=inf;
}
sort(q+,q+n+);
solve(,n);
printf("%lld\n",f[n]);
return ;
}
简单DP(20分)
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
#define rep(a,b,c) for(int a=(b);a>=(c);a--)
using namespace std; typedef long long ll;
const int N = 2e5+;
const ll inf = 1e18+; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} ll T[N],F[N],f[N],pre[N],n,s; int main()
{
freopen("in.in","r",stdin);
freopen("outr.out","w",stdout);
n=read(),s=read();
FOR(i,,n)
T[i]=read(),T[i]+=T[i-],F[i]=read(),F[i]+=F[i-] ;
FOR(i,,n) {
f[i]=inf;
FOR(j,,i-) {
//f[i]=min(f[i],f[j]+(F[n]-F[j])*(T[i]-T[j]+s));
int tmp=-T[i]*F[j]+(f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j]);
if(tmp<f[i]) pre[i]=j,f[i]=tmp;
}
f[i]+=F[n]*(T[i]+s);
}
printf("%lld\n",f[n]);
//FOR(i,1,n) {
// printf("%d %d\n",F[i],f[i]-F[n]*T[i]+F[i]*T[i]-s*F[i]);
//}
return ;
}
bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)的更多相关文章
- BZOJ 2726: [SDOI2012]任务安排 [斜率优化DP 二分 提前计算代价]
2726: [SDOI2012]任务安排 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 868 Solved: 236[Submit][Status ...
- 【BZOJ2726】[SDOI2012]任务安排 斜率优化+cdq分治
[BZOJ2726][SDOI2012]任务安排 Description 机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这N个任务被分成若 ...
- BZOJ 2726 [SDOI2012] 任务安排 - 斜率优化dp
题解 转移方程与我的上一篇题解一样 : $S\times sumC_j + F_j = sumT_i \times sumC_j + F_i - S \times sumC_N$. 分离成:$S\t ...
- BZOJ 2726: [SDOI2012]任务安排 斜率优化 + 凸壳二分 + 卡精
Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) # ...
- BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )
考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N) F, T均为后缀和. 与j有关 ...
- bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...
- bzoj 1492 [NOI2007]货币兑换Cash(斜率dp+cdq分治)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1492 [题意] 有AB两种货币,每天可以可以付IPi元,买到A券和B券,且A:B= ...
- bzoj 2726: [SDOI2012]任务安排
Description 机 器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这N个任务被分成若干批,每批包含相邻的 若干任务.从时刻0开始,这 ...
- 斜率dp cdq 分治
f[i] = min { f[j] + sqr(a[i] - a[j]) } f[i]= min { -2 * a[i] * a[j] + a[j] * a[j] + f[j] } + a[i] * ...
随机推荐
- 补发9.28“天天向上”团队Scrum站立会议
组长:王森 组员:张金生 张政 栾骄阳 时间:2016.09.28 地点:612寝 组员 已完成 未完成 王森 搭建初步原型 完善原型 张金生 更新UI设计 生成应用界面原型 张政 初步设计框架图 完 ...
- 8th 对软件工程的理解(读构建之法有感)
对于任何一个学计算机的人来说,软件都不陌生,甚至于一个普通的朝九晚五的上班族,他的每日生活工作也都与软件有着密不可分的关系.然而,程序又是如何从一行行指尖留下的代码,机器存储的数据变成快捷高效的软件的 ...
- 关于VS2005中C#代码用F12转到定义时,总是显示从元数据的问题
元数据是:NET 程序集中的标记信息. 是在代码中选择了转到定义时候给定位的吧.因为没有找到源代码,VS通过反射读取元数据中的信息生成了那个. 解决方法: 1. 要把项目先添加到解决方案中. 2. 再 ...
- 相见恨晚的 scala - 01 [ 基础 ]
简洁到不行,多一个分号都是不应该. 学习笔记: centOS 下安装 scala 和安装 jdk 一毛一样 . 1 . 不同于 Java 的变量声明 :( 但是和 js 很像 ) /** * Crea ...
- 浏览器本地存储(browser-storage)
https://www.baidufe.com/component/browser-storage/api.html 首页 | API参考 | 升级日志 BrowserStorage.api.set( ...
- PGM学习之七 MRF,马尔科夫随机场
之前自己做实验也用过MRF(Markov Random Filed,马尔科夫随机场),基本原理理解,但是很多细节的地方都不求甚解.恰好趁学习PGM的时间,整理一下在机器视觉与图像分析领域的MRF的相关 ...
- 在java中为什么要把main方法定义为一个static方法?
我们知道,在C/C++当中,这个main方法并不是属于某一个类的,它是一个全局的方法,所以当我们执行的时候,c++编译器很容易的就能找到这个main方法,然而当我们执行一个java程序的时候,因为ja ...
- static变量 方法 类 和final
static变量:声明为static的变量实质上就是全局变量.当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量.静态变量与静态方法类似.所有此类实例共 ...
- Vue使用SCSS进行模块化开发
原文地址:http://www.cnblogs.com/JimmyBright/p/7761531.html 个人认为scss最大的好处就是能将css属性设置为变量,这样让css一键更换主题成为可能. ...
- java追加写入txt文件
整理了下网上的资料,数据追加写入txt文件有三种方式,见下面代码: 方法一: public void method1() { FileWriter fw = null; try { //如果文件存在, ...