P8575 「DTOI-2」星之河 题解

P8575 「DTOI-2」星之河 题解

题目描述

P8575 「DTOI-2」星之河

题目解法

看题目就能感觉到是一道求偏序的题。所以我们先找偏序关系。

RediBluei 的关系题面已经给出,现在考虑子树关系。

自然而然地联想到 dfs 序。

先求出每个点的 dfs 序 dfni,以及其子树的大小 sizei

如果点 j 在点 i 的子树中,那么就有 dfni<dfnj<dfni+sizei

综上,可以得出 ji 有贡献的条件:

RedjRediBluejBlueidfni<dfnj<dfni+sizei

乍一看,好像是个四维偏序 (cdq 套 cdq)

但是由于最后一组条件比较特殊,可以化为三维偏序。

使用 cdq 分治。如果不会建议先做:【模板】三维偏序

在三维偏序模板中,用树状数组统计答案的时候统计的是 [1,xi) 该区间。

在本题中,用树状数组统计答案的时候我们统计 (dfni,dfni+sizei) 区间。

除此之外就是裸的 cdq 分治。

同时需要注意一下排序部分 Bluei,Redi 升序,而 dfni 降序。

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
vector<int> e[maxn];
int dfn[maxn], siz[maxn];
void dfs(int u, int f)
{
dfn[u]=++*dfn;
for(auto v:e[u])
if(v!=f)
dfs(v, u), siz[u]+=siz[v]+1;
}
struct st
{
int x, y, l, r, id;
st(int X, int Y, int L, int R, int I): id(I), x(X), y(Y), l(L), r(R){}
};
bool cmp1(st a, st b)
{
if(a.x!=b.x) return a.x<b.x;
if(a.y!=b.y) return a.y<b.y;
return a.l>b.l;
}
bool cmp2(st a, st b)
{
if(a.y!=b.y) return a.y<b.y;
if(a.l!=b.l) return a.l>b.l;
return a.x<b.x;
}
vector<st> vc;
template<typename Tp>
struct BIT:vector<Tp>
{
void modify(size_t i, Tp v) {for(;i<this->size();i+=i&-i) (*this)[i]+=v;}
Tp query(size_t i) {Tp r=0; for(;i;i-=i&-i) r+=(*this)[i]; return r;}
};
BIT<int> ta;
int ans[maxn];
void cdq(int l, int r)
{
if(l==r) return;
int mid=(l+r)>>1;
cdq(l, mid); cdq(mid+1, r);
sort(vc.begin()+l, vc.begin()+r+1, cmp2);
for(int i=l;i<=r;i++)
if(vc[i].x<=mid) ta.modify(vc[i].l, 1);
else ans[vc[i].id]+=ta.query(vc[i].r)-ta.query(vc[i].l-1);
for(int i=l;i<=r;i++)
if(vc[i].x<=mid)
ta.modify(vc[i].l, -1);
}
signed main()
{
int n;
cin>>n;
ta.resize(n+5);
for(int i=1, u, v;i<n;i++)
{
cin>>u>>v;
e[u].emplace_back(v);
e[v].emplace_back(u);
}
dfs(1, 0);
for(int i=1, r, b;i<=n;i++)
{
cin>>r>>b;
vc.emplace_back(r, b, dfn[i], min(dfn[i]+siz[i], n), i);
}
sort(vc.begin(), vc.end(), cmp1);
for(int i=0;i<vc.size();i++) vc[i].x=i;
cdq(0, n-1);
for(int i=1;i<=n;i++) if(ans[i]) cout<<ans[i]<<'\n';
}

本文作者:Jimmy-LEEE

本文链接:https://www.cnblogs.com/redacted-area/p/18379526

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(8)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起