【题解 P8575】 星之河
「DTOI-2」星之河
题目背景
星稀河影转,霜重月华孤。
题目描述
星之统治者有一个星盘,其可以被抽象为一棵根节点为
现在,星之统治者想要知道,对于每个节点
你需要按编号顺序依次输出每个节点的答案。为减少输出量,如果答案为
输入格式
第一行两个整数分别表示
接下来
接下来
输出格式
每个答案非
样例 #1
样例输入 #1
10
2 1
3 1
4 3
5 1
6 4
7 2
8 2
9 4
10 3
3 1
2 4
-3 3
4 -2
-2 3
-3 -6
-5 -1
-4 -7
-5 -1
-7 -7
样例输出 #1
5
2
3
1
提示
样例解释
对于节点
对于节点
对于节点
数据范围
特殊性质 | 总分数 | ||
---|---|---|---|
无 | |||
无 | |||
树的形态是链 | |||
无 |
对于所有数据,保证
解题思路
此题有些偏模板。
分析题意,就是找每个节点的子树中有多少个节点
利用欧拉序给每个节点编号,那么一个节点
可以转化为
多个询问,每次求节点号,
时间复杂度
Code
#include<bits/stdc++.h>
using namespace std;
struct datay
{
int p,x,y,op,v;
}a[600005],b[300005];
int n,dfn[200005],out[200005],num,m,f[200005];
vector<int> t[200005];
map<int,int> p;
set<int> g;
bool cmp1(datay q,datay w)
{
if(q.p!=w.p)return q.p<w.p;
return q.op<w.op;
}
bool cmp2(datay q,datay w)
{
if(q.x!=w.x)return q.x<w.x;
return q.op<w.op;
}
bool cmp3(datay q,datay w)
{
return q.op<w.op;
}
int lowbit(int x)
{
return x&(-x);
}
void clear(int x)
{
for(int i=x;i<=n;i+=lowbit(i))f[i]=0;
return;
}
void dijah(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))f[i]+=y;
return;
}
int gaia(int x)
{
int h=0;
while(x)
{
h+=f[x];
x-=lowbit(x);
}
return h;
}
void dfs(int x,int y)
{
dfn[x]=++num;
for(int i=0;i<t[x].size();i++)
{
if(t[x][i]==y)continue;
dfs(t[x][i],x);
}
out[x]=num;
return;
}
void cdq(int l,int r)
{
if(l==r)
{
return;
}
int mid=(l+r)>>1,x=l,y,z;
cdq(l,mid);
cdq(mid+1,r);
for(int i=mid+1;i<=r;i++)
{
while(x<=mid&&a[x].x<=a[i].x)
{
if(a[x].op==0)dijah(a[x].y,1);
x++;
}
a[i].v+=gaia(a[i].y);
}
for(int i=l;i<=mid;i++)
{
if(a[i].op==0)clear(a[i].y);
}
if(l==1&&r==3*n)return;
x=l,y=mid+1,z=1;
while(x<=mid&&y<=r)
{
if(a[x].x>a[y].x)b[z]=a[y],y++,z++;
else b[z]=a[x],x++,z++;
}
while(y<=r)b[z]=a[y],y++,z++;
while(x<=mid)b[z]=a[x],x++,z++;
for(int i=l;i<=r;i++)a[i]=b[i-l+1];
return;
}
int main()
{
int x,y,g1=0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
t[x].push_back(y);
t[y].push_back(x);
}
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
g.insert(a[i].y);
}
set<int>::iterator q=g.begin();
for(;q!=g.end();q++)
{
p[*q]=++g1;
}
for(int i=1;i<=n;i++)a[i].y=p[a[i].y];
dfs(1,0);
for(int i=1;i<=n;i++)a[i].p=dfn[i];
m=n;
for(int i=1;i<=n;i++)
{
a[++m].p=dfn[i];
a[m].op=2*i-1;
a[m].x=a[i].x;
a[m].y=a[i].y;
a[++m].p=out[i];
a[m].op=2*i;
a[m].x=a[i].x;
a[m].y=a[i].y;
}
sort(a+1,a+m+1,cmp1);
cdq(1,m);
sort(a+1,a+m+1,cmp3);
for(int i=n+1;i<=m;i+=2)
{
if(a[i+1].v==a[i].v)continue;
printf("%d\n",a[i+1].v-a[i].v);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现