适者

\[\sum_{i=1}^na_i\sum_{j=1}^ip_i-1 \]

\[考虑i,j \\ i在j前:sum+a_i*(p_i-1)+a_j*(p_i+p_j-1)=sum+a_i*p_i-a_i+a_j*p_i+a_j*p_j-a_j \\ j在i前:sum+a_j*(p_j-1)+a_i*(p_i+p_j-1)=sum+a_j*p_j-a_j+a_i*p_i+a_i*p_j-a_i \\ \delta =a_j*p_i-a_i*p_j \\ 于是i在j前的必要条件是,a_j*p_i<a_i*p_j \]

\[再考虑有秒杀的条件 \\ 考虑i被秒杀后的影响为t_i \\ t_i=(\sum_{j=1}^{i}(d_j-1)*a_i)+(\sum_{j=i+1}^{n}a_j*d_i) \\ 而对于i,j,产生的影响则为,t_i+t_j-a_i*d_j(等同于减去i的攻击在j的贡献) \]

\[再考虑固定i,则寻找j使上式最大 \\ 决策点j_1<j_2,f(j1)<f(j2) \\ t_{j_1}-a_id_{j_1}<t_{j_2}-a_id_{j_2} \\ a_i(d_{j_2}-d_{j_1})<t_{j_2}-t_{j_1} \\ 上凸壳 \]

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int MAXN=6e5+5;
int n;
int a[MAXN];
int dq[MAXN];
int d[MAXN];
int t[MAXN];
int sumw[MAXN];
int dp[MAXN];
struct Query{
	int pos;
	int sloop;
}query[MAXN],tmp[MAXN];
bool cmp(Query x,Query y)
{
//	return x.sloop<y.sloop;
	if(x.sloop==y.sloop)
	{
		return x.pos<y.pos;
	}
	return x.sloop>y.sloop;
}
int X(int i)
{
	return d[i];
}
int Y(int i)
{
	return t[i]; 
}
void solve(int l,int r)
{
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	
	int lpo=l;
	int rpo=mid+1;
	for(int i=l;i<=r;i++)
	{
		if(query[i].pos<=mid)
		{
			tmp[lpo++]=query[i];
		}else
		{
			tmp[rpo++]=query[i];
		}
	}
	for(int i=l;i<=r;i++)
	{
		query[i]=tmp[i];
	}
	solve(l,mid);
	int tail=0;
	for(int i=l;i<=mid;i++)
	{
		while(tail>1&&(Y(query[i].pos)-Y(dq[tail]))*(X(dq[tail])-X(dq[tail-1]))>=(X(query[i].pos)-X(dq[tail]))*(Y(dq[tail])-Y(dq[tail-1])))
		{
			tail--;
		}
		dq[++tail]=query[i].pos;
	}
	for(int i=mid+1;i<=r;i++)
	{
		while(tail>1&&query[i].sloop*(X(dq[tail])-X(dq[tail-1]))>=(Y(dq[tail])-Y(dq[tail-1])))
		{
			tail--;
		}
	//	printf("%d\n",dq[head]); 
		dp[query[i].pos]=max(dp[query[i].pos],t[query[i].pos]+t[dq[tail]]-a[query[i].pos]*d[dq[tail]]);
	}
	solve(mid+1,r);
	lpo=l;
	rpo=mid+1;
	int poi=l;
	while(lpo<=mid&&rpo<=r)
	{
		if((X(query[lpo].pos)<X(query[rpo].pos))||((X(query[lpo].pos)==X(query[rpo].pos)&&Y(query[lpo].pos)>Y(query[rpo].pos))))
		{
			tmp[poi++]=query[lpo++];
		}
		else
		{
			tmp[poi++]=query[rpo++];
		}
	}
	while(lpo<=mid)
	{
		tmp[poi++]=query[lpo++];
	}
	while(rpo<=r)
	{
		tmp[poi++]=query[rpo++];
	}
	for(int i=l;i<=r;i++)
	{
		query[i]=tmp[i];
	}
}
int ATK; 
struct node{
	int x,y;
}qr[MAXN];
bool XP(node x,node y)
{
	return y.x*x.y<y.y*x.x;
}
signed main()
{
	//freopen("1.in","r",stdin);
//	freopen("fight2.out","w",stdout);
	scanf("%lld %lld",&n,&ATK);
	int sumd=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld %lld",&a[i],&d[i]);
		d[i]=(d[i]-1)/ATK+1;
		//t[i]=
		qr[i].x=a[i];
		qr[i].y=d[i];
		
	}
	sort(qr+1,qr+1+n,XP);
	int ans=0;
	sumd=0;
	for(int i=1;i<=n;i++)
	{
		sumd+=(qr[i].y);
		ans+=((sumd-1)*qr[i].x); 
	}
	for(int i=1;i<=n;i++)
	{
		a[i]=qr[i].x;
		d[i]=qr[i].y;
	}
	
	sumd=0;
	for(int i=1;i<=n;i++)
	{
		sumd=sumd+(d[i]);
		t[i]=(sumd-1)*a[i];
	}

		int suma=0;
	for(int i=n;i>=1;i--)
	{
		t[i]+=suma*d[i];
		suma+=a[i];
	}
	for(int i=1;i<=n;i++)
	{
		query[i].pos=i;
		query[i].sloop=a[i];	
	}
	
	memset(dp,0,sizeof(dp));
	sort(query+1,query+1+n,cmp);
	solve(1,n);
	//printf("%lld",dp[n]);
	
	
	int rg=0;
	for(int i=1;i<=n;i++)
	{
		rg=max(rg,dp[i]);
	}
//	printf("%lld\n",ans);
	printf("%lld",ans-rg);
}
posted @ 2022-02-23 15:42  kid_magic  阅读(69)  评论(0编辑  收藏  举报