其他分享
首页 > 其他分享> > 【CF780G】Andryusha and Nervous Barriers 题解

【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