CDQ分治套斜率优化

CDQ分治套斜率优化

有一些特殊的动态规划题目,貌似可以化作\(\frac{g_j-g_k}{g'_j-g'_k}的斜率不等式,但实际上,\(g'_j\)以及\(g'_k\)却没有单调性,所以无法用单调队列/二分搜索单调栈实现斜率优化。于是,便有巨佬便想出了CDQ分治套斜率优化的方法。

如何CDQ?

对子状态按照\(K\)从小到大排序,分治,递归前,将子序列按照子状态的原下标分成两个子序列,子序列内部保持之前排序的顺序不变;

递归到子序列长度为\(1\)时,像普通斜率优化一样建点;

回溯时,将左子序列中的状态插入单调队列,像普通斜率优化一样对右子序列中的状态更新。

这样的话,当递归到底层时,当前子状态已经被所有原下标在自己之前的状态更新了。

例题: [SDOI2012]任务安排

代码实现:

#include
#include
#include
#include
#include
#include
#define int long long
#define maxn 300000
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
void read(int &x){
	int f=1;x=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	x*=f;
}
int A[maxn+5],B[maxn+5],F[maxn+5];
struct vec{
	int i,x,y;vec(){i=x=y=0;}
	vec(int x,int y){i=0,this->x=x,this->y=y;}
	vec(int i,int x,int y){this->i=i,this->x=x,this->y=y;}
	friend vec operator-(vec a,vec b){return vec(a.x-b.x,a.y-b.y);}
	friend bool operator<(vec a,vec b){if(a.x==0) return 0;return 1.0*a.y/a.x<1.0*b.y/b.x;}
} s[maxn+5],q[maxn+5],t[maxn+5];
int head=1,tail=0;
void push(vec x){
	while(tail>head&&(x-q[tail-1])<(q[tail]-q[tail-1])) tail--;
	q[++tail]=x;
}
void pop(int k){
	while(tail>head&&(q[head+1]-q[head])right||s[x1].x

你可能感兴趣的:(CDQ分治套斜率优化)