4700: 适者
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 43 Solved: 21
[ Submit][ Status][ Discuss]
Description
【题目背景】
“虽然不知道那两台是谁干掉的,不过任务完成了。”一一次祖伽密.
【题意描述】
敌方有n台人形兵器,每台的攻击力为Ai,护甲值为Di。我方只有一台人形兵器,攻击力为ATK。战斗看作回合制,
每回合进程如下:
·1 我方选择对方某台人形兵器并攻击,令其护甲值减少ATK,
若护甲值<0则被破坏。
·2 敌方每台未被破坏的人形兵器攻击我方基地造成Ai点损失。
但是,在第一回合开始之前,某两台敌方的人形兵器被干掉了(秒杀)。问最好情况下,我方基地会受到多少点损
失。
Input
第一行两个数n,ATK,表示敌方人形兵器数量和我方人形兵器攻击力。
接下来n行,每行两个数A,Di,表示对方第i台人形兵器的攻击力和护甲值。
3<=n<=3×10^5,Ai,Di<=10^4,ATK<10^4
Output
只一行,一个数,表示最好情况下我方基地会受到的损失总和。
Sample Input
3 7
30 8
7 35
1 209
30 8
7 35
1 209
Sample Output
28
【样例说明】
最好情况下,被秒杀的是敌方1、3号人形兵器,接下来需要5回合解决对方的2号人形兵器,对方共攻击4次,总计
造成28点伤害。可以证明没有更优的情况。
【样例说明】
最好情况下,被秒杀的是敌方1、3号人形兵器,接下来需要5回合解决对方的2号人形兵器,对方共攻击4次,总计
造成28点伤害。可以证明没有更优的情况。
这个题好气啊...
di=(D-1)/ATK+1,Pi=d1+d2+...+di,Ti=A1+A2+...+Ai
先考虑没有秒杀的情况,就按ai/di降序排序即可
假设在这个排好序上秒杀i,j(j<i),则ans-=aj*(Pj-1)+(Tn-Tj)*dj+ai*(Pi-1)*(Tn-Ti)*di-ai*dj
令Ki=ai*(Pi-1)+(Tn-Ti)*di,则求max{Ki+Kj-ai*dj}
是不是有点像斜率优化?
fi=Ki+Kj-ai*dj
ai*dj+fi-Ki=Kj 要使fi-Ki最大
ai,dj不递增?cdq分治即可
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 300005
using namespace std;
typedef long long ll;
int bh[maxn],q[maxn],bhd[maxn],bha[maxn];
int A[maxn],d[maxn],P[maxn],T[maxn],n,atk;
ll ans,pr,K[maxn];
int comp1(const int x,const int y){return A[x]*d[y]>A[y]*d[x];}
bool inline fc(int x,int y,int z){
ll x1=d[x], y1=K[x], x2=d[y], y2=K[y], x3=d[z], y3=K[z];
return (y1-y2)*(x2-x3)>=(y2-y3)*(x1-x2);
}
void cdq(int xl,int xr){
if(xl==xr)return ;
int mid=xl+xr>>1;
cdq(xl,mid);
cdq(mid+1,xr);
int l=1,r=0;
for(register int i=xl;i<=mid;++i){
while(l<r&&fc(bhd[i],q[r],q[r-1]))r--;
q[++r]=bhd[i];
}
for(register int i=mid+1;i<=xr;++i){
while(l<r&&K[q[l]]-K[q[l+1]]<=(ll)A[bha[i]]*(d[q[l]]-d[q[l+1]]))l++;
if(l<=r)ans=max(ans,K[bha[i]]+K[q[l]]-(ll)A[bha[i]]*d[q[l]]);
}
register int i=xl,j=mid+1,ptr=xl;
for(;i<=mid&&j<=xr;){
if(d[bhd[i]]<d[bhd[j]])bh[ptr++]=bhd[i++];
else bh[ptr++]=bhd[j++];
}
for(;i<=mid;)bh[ptr++]=bhd[i++];
for(;j<=xr;)bh[ptr++]=bhd[j++];
for(int i=xl;i<=xr;++i)bhd[i]=bh[i];
i=xl,j=mid+1,ptr=xl;
for(;i<=mid&&j<=xr;){
if(d[bha[i]]<d[bha[j]])bh[ptr++]=bha[i++];
else bh[ptr++]=bha[j++];
}
for(;i<=mid;)bh[ptr++]=bha[i++];
for(;j<=xr;)bh[ptr++]=bha[j++];
for(int i=xl;i<=xr;++i)bha[i]=bh[i];
}
int main(){
scanf("%d%d",&n,&atk);
for(register int i=1;i<=n;++i)bh[i]=i;
for(register int i=1;i<=n;++i){
scanf("%d%d",A+i,d+i);
d[i]=(d[i]-1)/atk+1;
}
sort(bh+1,bh+n+1,comp1);
for(register int i=1;i<=n;++i){
P[i]=P[i-1]+d[bh[i]];
T[i]=T[i-1]+A[bh[i]];
bhd[i]=bha[i]=bh[i];
}
for(register int i=1;i<=n;++i){
K[bh[i]]=(ll)A[bh[i]]*(P[i]-1)+(ll)(T[n]-T[i])*d[bh[i]];
pr+=(ll)A[bh[i]]*(P[i]-1);
}
cdq(1,n);
printf("%lld",pr-ans);
}