P8575 「DTOI-2」星之河 题解
前置知识
解法
增加一维为 DFS 序,然后就转化成了三维偏序问题,可以使用 CDQ 分治求解。
此时等价于求 \(red_{j} \le red_{i},blue_{j} \le blue_{i},dfn_{i}<dfn_{j} \le out_{i}\) 的 \(j\) 的数量。第三个限制条件前缀和维护即可。
注意按 DFS 序排序时,为保证子树内部节点能更新到根节点,需要降序排序。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
struct node
{
int a,b,dfn,out,id;
}a[200010];
int ans[200010],tot=0;
vector<int>e[200010];
bool cmpb(node a,node b)
{
return (a.b==b.b)?(a.dfn>b.dfn):(a.b<b.b);
}
bool cmpa(node a,node b)
{
return (a.a==b.a)?cmpb(a,b):(a.a<b.a);
}
void add(int u,int v)
{
e[u].push_back(v);
}
void dfs(int x,int fa)
{
tot++;
a[x].dfn=tot;
for(int i=0;i<e[x].size();i++)
{
if(e[x][i]!=fa)
{
dfs(e[x][i],x);
}
}
a[x].out=tot;
}
struct BIT
{
int dfn[200010];
int lowbit(int x)
{
return (x&(-x));
}
void add(int n,int x,int val)
{
for(int i=x;i<=n;i+=lowbit(i))
{
dfn[i]+=val;
}
}
int getsum(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i))
{
ans+=dfn[i];
}
return ans;
}
}T;
void cdq(int l,int r,int k)
{
if(l==r)
{
return;
}
int mid=(l+r)/2,x,y;
cdq(l,mid,k);
cdq(mid+1,r,k);
sort(a+l,a+mid+1,cmpb);
sort(a+mid+1,a+r+1,cmpb);
for(x=l,y=mid+1;y<=r;y++)
{
for(;a[x].b<=a[y].b&&x<=mid;x++)
{
T.add(k,a[x].dfn,1);
}
ans[a[y].id]+=T.getsum(a[y].out)-T.getsum(a[y].dfn);
}
x--;
for(int i=l;i<=x;i++)
{
T.add(k,a[i].dfn,-1);
}
}
int main()
{
int n,u,v,i;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs(1,0);
for(i=1;i<=n;i++)
{
cin>>a[i].a>>a[i].b;
a[i].id=i;
}
sort(a+1,a+1+n,cmpa);
cdq(1,n,n);
for(i=1;i<=n;i++)
{
if(ans[i]!=0)
{
cout<<ans[i]<<endl;
}
}
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18350810,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。