CF792F Mages and Monsters
Link
显然有用的马猴根据\(cps-dps\)构成了一个下凸包。
对于一个\(time,hp\)的怪,二分找到凸包上\(dps=\frac{hp}{time}\)所在直线,判断是否满足\(time*cps\le mp\)即可。
#include<set>
#include<cmath>
#include<cstdio>
#include<cctype>
using i64=long long;
namespace IO
{
char ibuf[(1<<23)+1],*iS=ibuf;
void In(){fread(ibuf,1,1<<23,stdin);}
i64 read(){i64 x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
}
using IO::read;
struct vec{int x,y;};
vec operator-(const vec&a,const vec&b){return {a.x-b.x,a.y-b.y};}
int operator<(const vec&a,const vec&b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
i64 operator*(const vec&a,const vec&b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
std::set<vec>s;
i64 lim;
void ins(vec x)
{
auto nxt=s.lower_bound(x),pre=prev(nxt);
if(nxt!=s.end()&&(*pre-x)*(*nxt-x)>=0) return ;
if(nxt!=s.end()) while(next(nxt)!=s.end()&&(x-*nxt)*(*next(nxt)-*nxt)>=0) ++nxt,s.erase(prev(nxt));
while(pre!=s.begin()&&(*prev(pre)-*pre)*(x-*pre)>=0) --pre,s.erase(next(pre));
s.insert(x);
}
int check(int a,int b)
{
auto nxt=s.lower_bound({(b-1)/a+1,0}),pre=prev(nxt);
return nxt==s.end()? 0:1ll*(nxt->x-pre->x)*a*pre->y+1ll*(nxt->y-pre->y)*(b-a*pre->x)<=lim*(nxt->x-pre->x);
}
int main()
{
IO::In();
int n=read();
lim=read(),s.insert({0,0});
for(int ans=0,i=1,opt,a,b;i<=n;++i) opt=read(),a=(read()+ans)%1000000+1,b=(read()+ans)%1000000+1,opt==1? ins({a,b}),0:check(a,b)? ans=i,puts("YES"):puts("NO");
}