Buffalo Barricades 题解

89 篇文章 1 订阅

Buffalo Barricades 题解

这题的难点在于某一头牛可能被多个农名占有。怎么处理呢?

我们仔细分析一下就会发现,每一个农名的篱笆最多被一个篱笆直接包含,所以我们把这些之间包含的农名之间连上边,最终形成的是一个森林。

但是我们一开始卡在了:一个农名包含某一个农名的篱笆,只有这个农名来的更早,才能得到包含的这个农名的牛,这其实就变成了一个三维偏序问题,不太容易解。

但其实我们可以从后往前将这些边加回来就可以了。

用dsu维护。

/*
{
######################
#       Author       #
#        Gary        #
#        2020        #
######################
*/
//#pragma GCC target ("avx2")
//#pragma GCC optimization ("O3")
//#pragma GCC optimization ("unroll-loops")
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int n;
vector<pair<mp,int> > event;
bool cmp(pair<mp,int>  A,pair<mp,int> B){
	if(A.FIR.SEC!=B.FIR.SEC){
		return A.FIR.SEC>B.FIR.SEC;
	}
	return A.SEC>B.SEC;
}
int ans[300000+20];
set<mp> barrier;
int fa[300000+20],con[300000+20];
int root(int x){
	return fa[x]=(fa[x]==x? x:root(fa[x]));
}
int main(){
	scanf("%d",&n);
	rb(i,1,n){
		int x,y;
		scanf("%d%d",&x,&y);
		event.PB(II(II(x,y),0));
	}	
	int m;
	scanf("%d",&m);
	rb(i,1,m){
		int x,y;
		scanf("%d%d",&x,&y);
		event.PB(II(II(x,y),i));
	}
	sort(ALL(event),cmp);
	for(auto eve:event){
		if(eve.SEC==0){
			auto ite=barrier.lower_bound(II(eve.FIR.FIR,-INF));
			if(ite==barrier.end()) continue;
			ans[ite->SEC]++;
		}
		else{
			int x,t;
			x=eve.FIR.FIR;
			t=eve.SEC;
			auto ite=barrier.upper_bound(II(x,t));
			if(ite!=barrier.end())
				con[eve.SEC]=ite->SEC;
			if(ite!=barrier.begin()){
				ite--;
				while(ite->SEC>t){
					bool break_=(ite==barrier.begin());
					set<mp> :: IT nex;
					if(!break_){
						nex=--ite;
						ite++;
					}
					barrier.erase(ite);
					if(break_) break;
					ite=nex;
				}	
			}
			barrier.insert(II(x,t));
		}
	}
	rb(i,1,m)
		fa[i]=i;
	vector<int> ans_;
	rl(i,m,1){
		ans_.PB(ans[i]);
		if(con[i]){
			fa[i]=root(con[i]);
//			cout<<i<<'-'<<root(i)<<' '<<con[i]<<endl;
			ans[root(i)]+=ans[i];
		}
	}
	reverse(ALL(ans_));
	for(auto it:ans_) 
	printf("%d\n",it);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值