【CF780G】Andryusha and Nervous Barriers 题解
作者:互联网
CF 传送门:CF780G Andryusha and Nervous Barriers
模拟 + 线段树套小根堆。
Solution
赛时读不懂题?想象力过于差劲。(审题错误)
上来发现直接模拟:给每一列都开一个小根堆(优化),内部插入这一列上方某一高度(行)有几个球存在,即初始时每一列都插入 make_pair(h+1,1)
。然后将挡板按高度从大到小排序(球肯定先到达高的挡板)。然后按序遍历所有挡板,对于一个挡板 \(i\) 的列区间范围 \([l_i,r_i]\) 内的每一列,都在其小根堆中查找有多少个球满足 \(h\leq s_i+u_i\),统计完所有列的、能掉出去的球的总数之后,再根据挡板位置把它们插入另外一列的小根堆并修改高度即可。
啊然后你就可以成功地 TLE 了。
要加上一个优化:若列区间 \([i,j]\) 中所有球的高度 的最小值大于 \(s_i+u_i\),那就不需要再去统计这个区间了。这个使用线段树维护即可。
啊然后你就可以成功卡过此题。所以说赛时多加加有的没的优化总是好的。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(register int i = a; i <= b; ++i)
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
const int maxn = 1e5 + 5, mod = 1e9 + 7, inf = 0x3f3f3f3f;
int h, w, n;
struct bz{
int u, l, r, s;
}b[maxn];
struct tree{
int mn;
priority_queue <pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
}t[maxn << 2];
bool operator <(bz const &x, bz const &y){
return x.u > y.u;
}
inline void up(int x){
t[x].mn = min(t[ls(x)].mn, t[rs(x)].mn);
}
inline void build(int i, int l, int r){
if(l == r){
t[i].pq.push(make_pair(h + 1, 1));
t[i].mn = h + 1; return;
} int mid = l + r >> 1;
build(ls(i), l, mid), build(rs(i), mid + 1, r), up(i);
}
inline int query(int i, int l, int r, int L, int R, int x){
if(t[i].mn > x) return 0;
if(l == r){
int res = 0;
while(t[i].pq.top().first <= x and t[i].pq.size()){
res = (res + t[i].pq.top().second) % mod, t[i].pq.pop();
}
if(t[i].pq.size()) t[i].mn = t[i].pq.top().first;
else t[i].mn = inf; return res;
} int mid = l + r >> 1, res = 0;
if(L <= mid) res = (res + query(ls(i), l, mid, L, R, x)) % mod;
if(R > mid) res = (res + query(rs(i), mid + 1, r, L, R, x)) % mod;
up(i); return res % mod;
}
inline void updt(int i, int l, int r, int pos, int x, int num){
if(l == r){
t[i].pq.push(make_pair(x, num));
t[i].mn = t[i].pq.top().first; return;
} int mid = l + r >> 1;
if(pos <= mid) updt(ls(i), l, mid, pos, x, num);
else updt(rs(i), mid + 1, r, pos, x, num); up(i);
}
signed main(){
scanf("%lld%lld%lld", &h, &w, &n);
rep(i, 1, n) scanf("%lld%lld%lld%lld", &b[i].u, &b[i].l, &b[i].r, &b[i].s);
sort(b + 1, b + n + 1);
build(1, 1, w);
rep(i, 1, n){
int cnt = query(1, 1, w, b[i].l, b[i].r, min(h + 1, b[i].s + b[i].u));
if(b[i].l == 1 and b[i].r == w) continue;
if(b[i].l == 1) updt(1, 1, w, b[i].r + 1, b[i].u, cnt * 2);
else if(b[i].r == w) updt(1, 1, w, b[i].l - 1, b[i].u, cnt * 2);
else updt(1, 1, w, b[i].r + 1, b[i].u, cnt), updt(1, 1, w, b[i].l - 1, b[i].u, cnt);
} printf("%lld\n", query(1, 1, w, 1, w, inf));
return 0;
}
标签:pq,res,int,题解,mn,mid,Nervous,Barriers,挡板 来源: https://www.cnblogs.com/gsn531/p/16496509.html