题解 CF780G【Andryusha and Nervous Barriers】

$\text{Link}$

提供一个暴力做法,模拟赛时过了。

题意

有一个 $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~

posted @ 2022-07-19 21:48  ffffyc  阅读(10)  评论(0)    收藏  举报  来源