80 分求助
查看原帖
80 分求助
456790
seantheone楼主2022/10/8 19:09

RT,思路就是求一个 dfn 序然后 cdq 三维偏序。

#include <bits/stdc++.h>
#define ll long long
#define _cst const
#define _IfD long long
#define _siz 20
using namespace std;
char buf[1<<_siz],buffer[1<<_siz],*p1=buf,*p2=buf,c='\n';
int op1=-1; _cst int op2=(1<<_siz)-1;
inline char gc(){return (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<_siz,stdin)),p1==p2?EOF:*p1++);}
inline void flush(){fwrite(buffer,1,op1+1,stdout),op1=-1;}
inline void pc(_cst char &x){if(op1==op2)flush();buffer[++op1]=x;}
template<typename T>void read(T &w){
	w=0;bool f=1;char ch=gc();
	for(;!isdigit(ch);ch=gc()) if(ch=='-')f=0;
	for(;'0'<=ch && ch<='9';ch=gc()) w=(w<<1)+(w<<3)+(ch^48);
	w=f?w:-w;
}template<typename T,typename ...Arg>void read(T &w,Arg &...arg){
	read(w); read(arg...);
}template<typename T>void wrt(T x){
  	if(x<0) pc('-'),x=-x;
	if(x>9) wrt(x/10);
	pc(x%10|48);
}template<typename T>void write(T x){
	wrt(x); pc(c);
}template<typename T,typename ...Arg>void write(T x,Arg ...arg){
	write(x); write(arg...);
}inline _IfD pow_10(_IfD x){
    _IfD base=10,ans=1;
    while(x) ans*=((x&1)?base:1),base*=base,x>>=1;
    return ans;
}template<typename T>void readd(T &w){
    w=0; _IfD x=0,cnt=0; bool f=1; char ch=gc();
    for(;ch<=32;ch=gc()); if(ch=='-')f=0;
    for(;'0'<=ch && ch<='9';ch=gc()) x=(x<<1)+(x<<3)+(ch^48);
    w=(T)(f?x:-x);
    if(ch!='.') return; x=0,ch=gc();
    for(;'0'<=ch && ch<='9';ch=gc(),++cnt) x=(x<<1)+(x<<3)+(ch^48);
    T tmp=(T)(x/(T)pow_10(cnt));
    w=w+(T)(f?tmp:-tmp);
}template<typename T,typename ...Arg>void readd(T &w,Arg &...arg){
	readd(w); readd(arg...);
}void readstr(string &s){
	char ch=gc();
	while(ch!='\n' && ch!=' ') s+=ch,ch=gc();
}void putstr(string s){
	int i=0; while(i<s.size()) pc(s[i++]);
}
template<typename T>inline T qmax(_cst T &a,_cst T &b){return a>b?a:b;}
template<typename T,typename ...Arg>inline T qmax(_cst T &a,_cst T &b,_cst Arg &...arg){return qmax(a,qmax(b,arg...));}
template<typename T>inline T qmin(_cst T &a,_cst T &b){return a<b?a:b;}
template<typename T,typename ...Arg>inline T qmin(_cst T &a,_cst T &b,_cst Arg &...arg){return qmin(a,qmin(b,arg...));}
template<typename T>inline void qswap(T &a,T &b){a+=b,b=a-b,a-=b;}

using namespace std;
const int MAXN=200005;

int n,tot=0;
vector<int> E[MAXN];

struct Node{int dfn,sze,r,b,id;}a[MAXN];
inline bool cmp1(const Node &a,const Node &b){
	if(a.r!=b.r) return a.r<b.r;
	if(a.b!=b.b) return a.b<b.b;
	return a.dfn+a.sze<b.dfn+b.sze;
}
inline bool cmp2(const Node &a,const Node &b){
	if(a.b!=b.b) return a.b<b.b;
	return a.dfn+a.sze<b.dfn+b.sze;
}

void dfs(int u,int fa){
	a[u].dfn=++tot,a[u].sze=1;
	for(int v:E[u])	if(v!=fa) dfs(v,u),a[u].sze+=a[v].sze; // 求 dfn 序,以及算子树大小 
}

int tr[MAXN<<2]; // 线段树维护单点+1、区间求和 
void upd(int p,int l,int r,int t,int k){
	if(l==r) return tr[p]+=k,void();
	int mid=(l+r)>>1;
	if(t<=mid) upd(p<<1,l,mid,t,k);
	else upd(p<<1|1,mid+1,r,t,k);
	tr[p]=tr[p<<1]+tr[p<<1|1];
}
int query(int p,int l,int r,int st,int en){
	if(l>en || r<st) return 0;
	if(st<=l && r<=en) return tr[p];
	int mid=(l+r)>>1;
	return query(p<<1,l,mid,st,en)+query(p<<1|1,mid+1,r,st,en);
}

int ans[MAXN];
void cdq(int l,int r){ // cdq 分治 
	if(l==r) return;
	int mid=(l+r)>>1;
	cdq(l,mid),cdq(mid+1,r); // 先递归左右两边 
	sort(a+l,a+mid+1,cmp2); // 排序 
	sort(a+mid+1,a+r+1,cmp2);
	int i=l;
	for(int j=mid+1;j<=r;j++){ // 双指针算贡献 
		while(i<=mid && a[i].b<=a[j].b) upd(1,1,n,a[i].dfn,1),i++; // 插入 dfn 的位置 
		ans[a[j].id]+=query(1,1,n,a[j].dfn+1,a[j].dfn+a[j].sze-1); // 查询子树内满足条件的数量 
	}
	for(int j=l;j<i;j++) upd(1,1,n,a[j].dfn,-1); // 清空线段树 
}

signed main(){
	read(n);
	for(int i=1;i<n;i++){
		int u,v; read(u,v);
		E[u].push_back(v);
		E[v].push_back(u); 
	}
	dfs(1,0); // 预处理 
	for(int i=1;i<=n;i++) read(a[i].r,a[i].b),a[i].id=i;
	sort(a+1,a+1+n,cmp1); // 按照 r,b,dfn 排序 
	
	cdq(1,n); // cdq 分治 
	for(int i=1;i<=n;i++)
		if(ans[i]!=0) write(ans[i]); // 输出 
	return flush(),0;
}
2022/10/8 19:09
加载中...