P11255 [GDKOI2023 普及组] 淋雨 题解
toolong114514 · · 题解
解题思路
我们不妨让时间拉长到原来的
接下来计算出每个雨滴
我们不妨把
定义
显然,
两个雨滴之间可以转移,当且仅当淋完一滴雨赶到另一滴雨落地处的时间小于等于落地时刻之差。
转移方程如下:
直接以此转移,时间复杂度约为
转移方程中的绝对值不太好处理,将其拆开如下:
整理可得
所有
直接无脑上 CDQ 分治优化 DP,第一维 sort 排序,第二维归并,第三维用树状数组维护最大值转移即可。
时间复杂度约为
参考代码
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
typedef long double db;
const int N=5e5+10;
struct ccf{
db pos,ti;
int xld;
}dot[N];
bool cmp1(ccf pre,ccf nxt){
return pre.ti<nxt.ti;
}
bool cmp2(ccf pre,ccf nxt){
return pre.pos<nxt.pos;
}
bool cmp3(ccf pre,ccf nxt){
return pre.pos>nxt.pos;
}
db v_w,v_g,v_c;
int n,q,ans;
int f[N];
db num[N];
int cnt;
int get_pos(db x){
int l=1,r=cnt;
while(l<=r){
int mid=(l+r)/2;
if(x<num[mid]) r=mid-1;
else if(x>num[mid]) l=mid+1;
else return mid;
}
}
int lowbit(int x){return x&-x;}
int arr[N];
void upd(int x,int y){
while(x<=cnt){
arr[x]=max(arr[x],y);
x+=lowbit(x);
}
}
int ask(int x){
int res=0;
while(x>0){
res=max(res,arr[x]);
x-=lowbit(x);
}
return res;
}
void cdq(int l,int r){
if(l==r){
f[dot[l].xld]=max(f[dot[l].xld],1);
return;
}
int mid=(l+r)/2;
cdq(mid+1,r);
cnt=0;
for(int i=l;i<=r;i++){
num[++cnt]=dot[i].pos+dot[i].ti;
}
sort(num+1,num+cnt+1);
cnt=unique(num+1,num+cnt+1)-num-1;
for(int i=1;i<=cnt;i++){
arr[i]=0;
}
sort(dot+l,dot+mid+1,cmp2);
sort(dot+mid+1,dot+r+1,cmp2);
int i=l,j=mid+1;
while(i<=mid){
while(j<=r&&dot[i].pos>=dot[j].pos){
if(dot[j].xld>q) upd(cnt-get_pos(dot[j].pos+dot[j].ti)+1,f[dot[j].xld]);
j++;
}
f[dot[i].xld]=max(f[dot[i].xld],(ask(cnt-get_pos(dot[i].pos+dot[i].ti)+1)+1));
i++;
}
cnt=0;
for(i=l;i<=r;i++){
num[++cnt]=dot[i].pos-dot[i].ti;
}
sort(num+1,num+cnt+1);
cnt=unique(num+1,num+cnt+1)-num-1;
for(i=1;i<=cnt;i++){
arr[i]=0;
}
sort(dot+l,dot+mid+1,cmp3);
sort(dot+mid+1,dot+r+1,cmp3);
i=l,j=mid+1;
while(i<=mid){
while(dot[i].pos<=dot[j].pos&&j<=r){
if(dot[j].xld>q) upd(get_pos(dot[j].pos-dot[j].ti),f[dot[j].xld]);
j++;
}
f[dot[i].xld]=max(f[dot[i].xld],ask(get_pos(dot[i].pos-dot[i].ti))+1);
i++;
}
sort(dot+l,dot+mid+1,cmp1);
cdq(l,mid);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>q>>v_g>>v_w>>v_c;
v_g/=v_c,v_w/=v_c;
for(int i=q+1;i<=q+n;i++){
db xx,yy;
cin>>xx>>yy;
dot[i].xld=i;
dot[i].ti=yy/v_g;
dot[i].pos=xx+v_w*dot[i].ti;
}
for(int i=1;i<=q;i++){
cin>>dot[i].pos;
dot[i].ti=0;
dot[i].xld=i;
}
sort(dot+1,dot+n+q+1,cmp1);
cdq(1,n+q);
for(int i=1;i<=q;i++){
cout<<f[i]-1<<'\n';
}
return 0;
}
AC record
Written by toolong114514 on 2025/8/18.