zoukankan      html  css  js  c++  java
  • luogu P5785 [SDOI2012]任务安排 斜率dp+二分

    //k可能是负数,所以斜率不在有单调性
    //新加的点的横坐标还是单调递增的,但可能不是严格的
    //在查询的时候:只能二分查找
    //在插入的时候:将队尾不在凸包上的点删掉
    
    //f[j]=(sumt[i]+s)*sumc[j]+f[i]-sumt[i]*sumc[i]-s*sumc[n]
    //f[i]=f[j]-(sumt[i]+s)sumc[j]+sumt[i]*sumc[i]+s*sumc[n]
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    const int N = 3e5 + 10;
    int n, s;
    LL sc[N], st[N];
    LL f[N];
    int q[N];
    double Y(int i)
    {
    	return (double)f[i];
    }
    double X(int i)
    {
    	return (double)sc[i];
    }
    double slope(int i,int j)
    {
    	if(X(i)-X(j)<-1e5)
    		return 1e9;
    	return (double)(Y(i)-Y(j))/(X(i)-X(j));
    }
    int main()
    {
    	cin>>n>>s;
    	for(int i=1; i<=n; i++)
    	{
    		cin>>st[i]>>sc[i];
    		st[i]+=st[i-1];
    		sc[i]+=sc[i-1];
    	}
    	int hh=0,tt=0;
    	//f[j]=(sumt[i]+s)*sumc[j]+f[i]-sumt[i]*sumc[i]-s*sumc[n]
    	//f[i]=f[j]-(sumt[i]+s)sumc[j]+sumt[i]*sumc[i]+s*sumc[n]
    	for(int i=1; i<=n; i++)
    	{
    		int l=hh,r=tt;
    		while(l<r)
    		{
    			int mid=l+r>>1;
    			if(slope(q[mid+1],q[mid])>st[i]+s)
    				r=mid;
    			else
    				l=mid+1;
    		}
    		f[i]=f[q[l]]-(st[i]+s)*sc[q[l]]+st[i]*sc[i]+s*sc[n];
    		while(hh<tt&&slope(i,q[tt-1])<=slope(q[tt],q[tt-1]))
    			tt--;
    		q[++tt]=i;
    	}
    	cout<<f[n]<<endl;
    }
    
    
  • 相关阅读:
    不容易系列之一(错排)
    找新朋友(欧拉函数)
    二分查找
    快速排序(分治)
    归并排序(分治)
    畅通工程(并查集)
    A Knight's Journey (DFS)
    Network Saboteur (DFS)
    Oil Deposits(油田)(DFS)
    Dungeon Master (三维BFS)
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12909629.html
Copyright © 2011-2022 走看看