题解 CF780G【Andryusha and Nervous Barriers】
提供一个暴力做法,模拟赛时过了。
题意
有一个 $h\times w$ 的屏幕,屏幕上方每列有一个小球,你可以认为它们的初始高度为 $h+1$。小球会沿所在列竖直下落。
屏幕上有 $n$ 个挡板,第 $i$ 个挡板在 $u_i$ 的高度,位于 $[l_i,r_i]$ 之间的列,拥有属性 $s_i$。
具体地,当一个从高度 $t$ 开始掉落的小球落在挡板 $i$ 上时,
- 若 $i>u_i+s_i$,则 $i$ 会直接穿过当前挡板(不重新计算开始掉落高度);
- 否则,该球会分裂为两个小球,分别在 $l_i-1$ 和 $r_i+1$ 列,从高度为 $u_i$ 的地方开始下落。若上面两列有一个不在屏幕内,则对应的小球变到另一边。
保证一行最多只有一个挡板。
$n,w\le 10^5$,$h_i\le 10^9$。
思路
声明:本题解仅为比较优秀的暴力,过了 CF 数据。如有需要请忽略本题解。
考虑到除了 $h+1$ 行,每一行都最多只有 $2$ 列有小球。
对于第 $h+1$ 行,维护并查集以支持快速删除/查找区间剩余小球位置。和这个一样。(这部分复杂度是正确的)
对于其余行,对所有有球的行维护 set,每次查询、删除时遍历符合条件的所有行,并将其区间内的点删去。
复杂度正确的做法有 KD-Tree,线段树对列维护 set 之类,其余题解有讲,且都较为直观,本题解便不做说明。
代码:
甚至跑到了最优解。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=3e5+10,mod=1e9+7;
int h,w,n;
struct block{
int u,l,r,s;
inline friend bool operator<(const block &a,const block &b){
return a.u>b.u;
}
}b[N];
vector<int>num;
inline int find(int x){
return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
int f[N];
inline int findf(int x){
return x==f[x]?x:f[x]=findf(f[x]);
}
struct node{
int u;
mutable int p1,p2,c;
int cc;
inline friend bool operator<(const node &a,const node &b){
return a.u>b.u;
}
inline friend bool operator<(const node &a,const int &b){
return a.u>b;
}
};
set<node>hx;
inline bool ins(int x,int l,int r){
return l<=x&&x<=r;
}
int main(){
h=read(),w=read(),n=read();
for(int i=1;i<=n;i++)
b[i].u=read(),b[i].l=read(),
b[i].r=read(),b[i].s=read()+b[i].u;
for(int i=1;i<=w+1;i++)
f[i]=i;
sort(b+1,b+n+1);
num.push_back(h+1);
for(int i=1;i<=n;i++)
num.push_back(b[i].u),
num.push_back(b[i].s);
sort(num.begin(),num.end());
num.resize(unique(num.begin(),num.end())-num.begin());
int tmp=find(h+1),L=num.size()+10;
for(int i=1;i<=n;i++){
int u=find(b[i].u),l=b[i].l,r=b[i].r,s=find(b[i].s);
int c=0;
if(s>=tmp){
for(int i=findf(l);i<=r;i=findf(i))
c++,f[i]=i+1;
}
int t=s;
auto it=hx.lower_bound({t,0,0,0,0});
for(;it!=hx.end();){
node tmp=*it;
if(tmp.p1&&ins(tmp.p1,l,r)) tmp.p1=0,tmp.c--,c=(c+tmp.cc)%mod;
if(tmp.p2&&ins(tmp.p2,l,r)) tmp.p2=0,tmp.c--,c=(c+tmp.cc)%mod;
t=tmp.u-1;
if(tmp.c==0) hx.erase(it);
else it->p1=tmp.p1,it->p2=tmp.p2,it->c=tmp.c;
it=hx.lower_bound({t,0,0,0,0});
}
if(!c) continue;
if(l<=1) hx.insert({u,r+1,r+1,2,c});
else if(r>=w) hx.insert({u,l-1,l-1,2,c});
else hx.insert({u,l-1,r+1,2,c});
}
int ans=0;
for(int i=findf(1);i<=w;i=findf(i+1))
ans++,f[i]=i+1;
for(auto x:hx)
ans=(ans+1ll*x.cc*x.c)%mod;
write(ans);
flush();
}
再见 qwq~

浙公网安备 33010602011771号