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;
}