把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

2019.7.15 义乌模拟赛 T4 白云的花费

感觉像是一种模拟费用流。
首先这个东西费用的计算式为\(P_i+(j-i)\times m\)
拆开变成\(P_i-mi+mj\),这个东西对于两边独立。那么我们维护一个关于\(P_i-mi\)的单调上升的单调队列。
对于越往前的位置费用越小,但是流量越小。
那么挨个弹飞即可,然后对单调队列打上整体标记。
时间复杂度\(O(nlogn)\)瓶颈在LIS上
code:

#include<bits/stdc++.h>
#define I inline
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 1000000
#define M 50000
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define R(x) (rand()*rand()%x+1)
using namespace std;
int n,fl[N+5],Q[N+5],head,tail;ll ans,W[N+5],V,D[N+5],P[N+5],F[N+5],tot,m;
I void read(ll &x){
	char s=Gc();x=0;while(s<'0'||s>'9') s=Gc();
	while(s>='0'&&s<='9') x=x*10+s-48,s=Gc();
}
struct Getline{
	int dp[N+5],las[N+5],l,r,F[N+5],val[N+5],nows[N+5],tots[N+5],mid,now;
	I void ls(int  &x){l=0;r=n+1;while(l+1<r) mid=l+r>>1,(nows[mid]<x?l:r)=mid;x=tots[r];}
	I int max(int x,int y){return (dp[x]==dp[y])?(x<y?x:y):(dp[x]>dp[y]?x:y);}
	I void insert(int x,int y){while(x<=n)F[x]=max(F[x],y),x+=x&-x;}
	I int find(int x){int ans=0;while(x) ans=max(ans,F[x]),x-=x&-x;return ans;}
	I void swap(int &x,int &y){x^=y^=x^=y;}
	I void calc(){
		re int i;for(i=1;i<=n;i++) nows[i]=val[i];sort(nows+1,nows+n+1);for(tots[1]=1,i=2;i<=n;i++) tots[i]=tots[i-1]+(nows[i]!=nows[i-1]);
		for(i=1;i<=n;i++) ls(val[i]);for(i=1;i<=n;i++) las[i]=find(val[i]-1),dp[i]=dp[las[i]]+1,insert(val[i],i),now=now>dp[i]?now:dp[i];
		for(i=1;i<=n;i++) if(dp[i]==now){now=i;break;}for(;now;now=las[now]) fl[now]=1;
	}
}S;
I void solve(int l,int r){
	re int i;for(i=l;i<=r;i++)W[i]=P[i]-i*m;head=tail=tot=0;
	for(i=l;i<=r;i++){
		while(head^tail&&W[Q[tail]]>W[i]) tail--; Q[++tail]=i;F[i]=tot+D[i]+1;
		while(head^tail){//if(F[Q[head+1]]<=tot){head++;continue;}
			if(D[i]<=F[Q[head+1]]-tot){ans+=D[i]*(W[Q[head+1]]+i*m);tot+=D[i];D[i]=0;break;}
			ans+=(F[Q[head+1]]-tot)*(W[Q[head+1]]+i*m);D[i]-=F[Q[head+1]]-tot;tot=F[Q[++head]];
		}F[i]=V+tot;//printf("%lld\n",ans);
	}
}
int main(){
	freopen("new.in","r",stdin);freopen("new.out","w",stdout);
	re int i,j;scanf("%d%lld%lld",&n,&m,&V);for(i=1;i<=n;i++) scanf("%d",&S.val[i]);for(i=1;i<=n;i++) read(D[i]);for(i=1;i<=n;i++) read(P[i]);S.calc();
	for(i=1;i<=n;i=j+1){
		for(j=i+1;!fl[j]&&j<=n;j++);j--;solve(i,j);
	}printf("%lld\n",ans);
}
posted @ 2021-07-15 21:30  275307894a  阅读(40)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end