zoukankan      html  css  js  c++  java
  • 任务安排「SDOI2012」

    题意

    有一个数列,每个元素均有一个完成耗时(t_i)与完成耗费(f_i),每个元素的耗费等于其完成时刻乘以完成耗费。可以将这些元素分为任意组,每一组的元素完成时刻一样。每一组都会有一个固定的额外时间耗费(s)。数据范围(3*10^5)


    思路

    首先推出状态转移方程(dp[i]=min(dp[j]+s*(sumf[n]-sumf[j])+sumt[i]*(sumf[i]-sumf[j])))

    拆开可以得到斜率

    (frac{dp[j]-dp[k]}{sumf[j]-sumf[k]}>s+sumt[i])

    然而斜率不具有单调性,因此考虑(CDQ)分治。

    左侧直接更新右侧即可。


    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	#define int long long
    	
    	const int N=300300;
    //	const int INF=2147483647;
    	
    	int n,s,head,tail;
    	int t[N],f[N],dp[N];
    	struct node {
    		int id;
    		int x,y;
    		node () {}
    		node (int _x,int _y) : x(_x),y(_y) {}
    		friend node operator + (const node &x,const node &y) {
    			return node(x.x+y.x,x.y+y.y);
    		}
    		friend node operator - (const node &x,const node &y) {
    			return node(x.x-y.x,x.y-y.y);
    		}
    		friend int operator * (const node &x,const node &y) {
    			return x.x*y.y-x.y*y.x;
    		}
    	} w[N],queue[N],tmp[N];
    	
    	inline bool cmpid (const node &x,const node &y) {
    		return t[x.id]<t[y.id];
    	}
    	inline bool cmpx (const node &x,const node &y) {
    		return (x.x==y.x)?(x.y<y.y):(x.x<y.x);
    	}
    	inline double slope (node x,node y) {
    		return static_cast<double>(x.y-y.y)/static_cast<double>(x.x-y.x);
    	}
    	void merge1 (int l,int r) {
    		int mid=(l+r)>>1,ptr_l=l,ptr_r=mid+1;
    		for (register int i=l; i<=r; ++i) {
    			if (w[i].id<=mid) tmp[ptr_l++]=w[i];
    			else tmp[ptr_r++]=w[i];
    		}
    		for (register int i=l; i<=r; ++i) w[i]=tmp[i];
    	}
    	void merge2 (int l,int r) {
    		int mid=(l+r)>>1,ptr_l=l,ptr_r=mid+1;
    		for (register int i=l; i<=r; ++i) {
    			if (ptr_l<=mid&&(ptr_r>r||cmpx(w[ptr_l],w[ptr_r]))) tmp[ptr_l++]=w[i];
    			else tmp[ptr_r++]=w[i];
    		}
    		for (register int i=l; i<=r; ++i) w[i]=tmp[i];
    	}
    	void CDQ (int l,int r) {
    		if (l==r) return w[l].x=f[w[l].id],w[l].y=dp[w[l].id],void();
    		int mid=(l+r)>>1;merge1(l,r),CDQ(l,mid),head=1,tail=0;
    		for (register int i=l; i<=mid; ++i) {
    			while (head<tail&&(queue[tail]-queue[tail-1])*(w[i]-queue[tail-1])<0) --tail;
    			queue[++tail]=w[i];
    		}
    		for (register int i=mid+1; i<=r; ++i) {
    			while (head<tail&&slope(queue[head+1],queue[head])<s+t[w[i].id]) ++head;
    			dp[w[i].id]=min(dp[w[i].id],dp[queue[head].id]+s*(f[n]-f[queue[head].id])+t[w[i].id]*(f[w[i].id]-f[queue[head].id]));
    		}
    		CDQ(mid+1,r),merge2(l,r);
    	}
    
    	inline void MAIN () {
    		read(n),read(s);
    		for (register int i=1; i<=n; ++i) read(t[i]),read(f[i]),t[i]+=t[i-1],f[i]+=f[i-1],w[i].id=i;
    		sort(w+1,w+n+1,cmpid),memset(dp,0x3f,sizeof(dp)),dp[0]=0,CDQ(0,n);
    		write(dp[n]);
    	}
    	
    	#undef int
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
  • 相关阅读:
    SQL数据库一直显示正在还原
    jQuery获取display为none的隐藏元素的宽度和高度的解决方案
    火狐打开新标签页面不出现九宫格的设置
    【转】在C#中?,?:和??
    【转】JS字符(字母)与ASCII码转换方法
    如何为 .NET Core 安装本地化的 IntelliSense 文件
    compass typography 排版 常用排版方法[Sass和compass学习笔记]
    单元测试 逃不开的Done 与约定
    SASS+COMPASS 自适应 学习笔记
    compass tables 表格 表格常见样式[Sass和compass学习笔记]
  • 原文地址:https://www.cnblogs.com/ilverene/p/11379371.html
Copyright © 2011-2022 走看看