题解 P4803
a326820068122c · · 题解
巧了我也是随机跳到这题的。
这题大体做法和上一篇题解差不多。
题目大意是给定
这里可以发现交点显然不优,因为通过交点的其他飞机挡不了它。
由于对于一架飞机
提供一个小优化。
就是由于 st表解决)。
这样时间复杂度从
所以这题根本用不着个
另外这题建议用long double以保证精度。
有一个小细节,就是为了不把交点算进来,需要略微减少一下查询两端的距离。
发一下代码:
#include <bits/stdc++.h>
#define for1(i,n) for(i=1;i<=(n);i++)
#define for0(i,n) for(i=0;i<=(n);i++)
#define mems(a) memset(a,0,sizeof(a))
using namespace std;
typedef long double ld;
typedef long long ll;
const int N=2005,M=800005;
const ld eps=1e-10;
int m,d,n,cq,b[N],c[N],q[N],lq,rq;
ll ans[M],dp[N];
ld k[N],t[N],l[M];
vector<int> v[N],u[N];
bool dy(const ld &x,const ld &y){return abs(x-y)<eps;}
struct node{
ld x;
ll f;
bool operator<(const node &nd)const{return x<nd.x;}
}p[N],s[N];
bool cmp(const int &x,const int &y){return l[x]<l[y];}
int main(){
scanf("%d%d%d%d",&m,&d,&n,&cq);
int i,j,x,cs,cp;
ld z;
for1(i,n) scanf("%d%d%d",&b[i],&x,&c[i]),k[i]=(ld)(x-b[i])/m;
for1(i,cq) scanf("%d%Lf",&x,&l[i]),l[i]+=d-5e-11,v[x].push_back(i);
for1(i,n){
cs=cp=lq=rq=q[0]=dp[0]=0;
for1(j,n){
if(b[j]>b[i]) dp[0]+=c[j];
if(!dy(k[i],k[j])){
z=(b[i]-b[j])/(k[j]-k[i]);
if(z>=0&&z<=m) p[++cp]={z,k[j]>k[i]?c[j]:-c[j]};
}
}
sort(p+1,p+cp+1);
for1(j,cp){
if(dy(p[j].x,p[j-1].x)) s[cs].f+=p[j].f;
else s[++cs]=p[j];
}
t[cs+1]=m;
for0(j,cs) u[j].clear(),t[j]=s[j].x;
for(int y:v[i]) u[upper_bound(t+1,t+cs+1,l[y])-t-1].push_back(y);
for1(j,cs+1){
sort(u[j-1].begin(),u[j-1].end(),cmp);
for(int y:u[j-1]){
while(l[y]-t[q[lq]+1]>d-eps) lq++;
ans[y]=dp[q[lq]];
}
if(j>cs) break;
dp[j]=dp[j-1]+s[j].f;
while(t[j]-t[q[lq]+1]>d-eps) lq++;
while(lq<=rq&&dp[j]>=dp[q[rq]]) rq--;
q[++rq]=j;
}
}
for1(i,cq) printf("%lld\n",ans[i]);
return 0;
}