首页 > 其他分享 >【题解 P8575】 星之河

【题解 P8575】 星之河

时间:2024-01-24 16:34:35浏览次数:39  
标签:P8575 10 le 小于 ++ 题解 星之河 text 节点

「DTOI-2」星之河

题目背景

星稀河影转,霜重月华孤。

题目描述

星之统治者有一个星盘,其可以被抽象为一棵根节点为 \(1\) 的树。树上每个节点 \(i\) 有一颗红星、一颗蓝星,亮度分别记为 \(\text{Red}_i,\text{Blue}_i\)。

现在,星之统治者想要知道,对于每个节点 \(x\),其子树内(不包括该节点)有多少节点满足:其红星亮度小于等于 \(x\) 的红星亮度,且其蓝星亮度小于等于 \(x\) 的蓝星亮度。

你需要按编号顺序依次输出每个节点的答案。为减少输出量,如果答案为 \(0\) 则不必输出。

输入格式

第一行两个整数分别表示 \(n\)。

接下来 \(n-1\) 行每行两个正整数 \(u,v\),表示存在 \((u,v)\) 这条树边。

接下来 \(n\) 行每行两个整数分别表示 \(\text{Red}_i, \text{Blue}_i\)。

输出格式

每个答案非 \(0\) 的节点一行,每行一个整数表示答案。

样例 #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

提示

样例解释

对于节点 \(1\),小于等于他的子节点有 \(6,7,8,9,10\),因此输出 \(5\)。
对于节点 \(4\),小于等于他的子节点有 \(6\),因此输出 \(1\)。
对于节点 $5 $ 至 \(10\),没有小于等于他的子节点,因此不输出。

数据范围

\(\textbf{Subtask}\) \(n\le\) 特殊性质 总分数
\(1\) \(1000\) \(10\)
\(2\) \(5\times 10^4\) \(20\)
\(3\) \(10^5\) \(-200\le \text{Red}_i, \text{Blue}_i \le 200\) \(20\)
\(4\) \(2\times 10^5\) 树的形态是链 \(20\)
\(5\) \(2\times 10^5\) \(30\)

对于所有数据,保证 \(n \le 2\times 10^5\),\(-10^9 \le \text{Red}_i, \text{Blue}_i \le 10^9\)。

解题思路

此题有些偏模板。
分析题意,就是找每个节点的子树中有多少个节点 \(red\) 和 \(blue\) 都小于自己。
利用欧拉序给每个节点编号,那么一个节点 \(x\) 的子树范围就是 \(dfn_x+1\) 到 \(out_x\) ,不包获该节点。
可以转化为 \(1\) 到 \(dfn_x+1\) 与 \(out_x\) 中,满足要求的有多少个,相减即可。
多个询问,每次求节点号,\(red\) ,\(blue\) 都小于自己的有多少个节点,三维偏序问题。
\(CDQ\) 分治解决,先在分治外确定完一维,分治内部合并时排序第二维,最后一维用树状数组即可。
时间复杂度 \(O(nlog^2n)\) 。

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

标签:P8575,10,le,小于,++,题解,星之河,text,节点
From: https://www.cnblogs.com/dijah/p/17984977

相关文章

  • 题解 P9911 [COCI 2023/2024 #2] Kuglice
    传送门。题意应该是显然的.分析首先,观察数据范围:\(1\len\le3000\),也就是说,时间复杂度应当在\(O(n^2)\)左右。其次,观察我们取球的顺序,是只能从左或右取,因此,我们每次留下的必然是连续的一段。所以,我们显然可以采用区间DP来解决这道题。确定状态:\(f_{i,j}\)表示现在取......
  • CF1689A题解
    题意简述给定字符串\(a\)和\(b\),每次从\(a\)串或\(b\)串中选出一个字符加入\(c\)串,要求\(c\)串的字典序最小。特别地,在\(c\)串中不能出现连续\(k\)次来源相同的字符。思维路径由于字符是随意选取的,易于发现每次选\(a\)串中字典序最小的字符或者\(b\)串中字......
  • CF911G Mass Change Queries 题解
    题目链接:CF或者洛谷前置知识点:平衡树合并:CF文章与维基百科看上去这题有很多人用线段树分裂与合并去做,其实这种需要分裂和合并的,我们用文艺平衡树去维护区间信息是最容易写的。考虑本题的特殊性,值域并不是很大,所以其实我们可以为每种值开一棵文艺平衡树,而平衡树维护的值为......
  • [SNOI2024]公交线路 题解
    为啥洛谷现有的题解全是\(O(n^2\logn)\)的做法?给个好写的\(O(n^2)\)做法。感觉这题是这套题中除了D1T1以外最简单的题(显然最远的距离一定由两个叶子贡献,我们拎出一个非叶节点为根,分析一些性质。考虑两个叶子\(u,v\)何时距离\(\le2\),这要求它们所一步能到达的最浅点......
  • 【题解 P4197】 Peaks
    Peaks题目描述在Bytemountains有\(n\)座山峰,每座山峰有他的高度\(h_i\)。有些山峰之间有双向道路相连,共\(m\)条路径,每条路径有一个困难值,这个值越大表示越难走。现在有\(q\)组询问,每组询问询问从点\(v\)开始只经过困难值小于等于\(x\)的路径所能到达的山峰中第\(......
  • 【题解 P3293】 美味
    [SCOI2016]美味题目描述一家餐厅有\(n\)道菜,编号\(1,2,\ldots,n\),大家对第\(i\)道菜的评价值为\(a_i\)。有\(m\)位顾客,第\(i\)位顾客的期望值为\(b_i\),而他的偏好值为\(x_i\)。因此,第\(i\)位顾客认为第\(j\)道菜的美味度为\(b_i\oplus(a_j+x_i)\),\(\opl......
  • 2024寒假集训 进阶训练赛 (六)部分题解
    A统计单词数题解注意是否是单词。CODECPP#include<iostream>#include<string>#include<algorithm>usingnamespacestd;intmain(){stringword,article;getline(cin,word);getline(cin,article);//转换为小写字母transform(word.beg......
  • Romberg 数值积分算法+P3779 题解(马上写完)
    Romberg算法吊打Simpson的且不玄学(没有什么十五倍)的数值积分算法。缺点是过程复杂一点,但是只体现在证明上,代码很短。铺垫算法梯形求积公式公式\[\int_a^bf(x)dx\approx\frac{(f(a)+f(b))(b-a)}2\\\text{令}(1)=\frac{(f(a)+f(b))(b-a)}2\]计算梯形求积公式的误差......
  • 前端打包后上传至服务器,发现css样式都未生效,查看请求preview预览格式不正确问题解决
    参考:https://blog.csdn.net/wzj_110/article/details/112850811 我的问题前端打包后上传至服务器,发现css样式都未生效,查看css请求,发现preview预览格式不正确,Response-Headers里的Content-type未对应 原因服务器的nginx配置中, mime.types文件缺失。 原理 MIME:Multip......
  • P2627 [USACO11OPEN] Mowing the Lawn G ( [USACO Open11] 修剪草坪/P2034 选择数字 )题
    P2627[USACO11OPEN]MowingtheLawnG搬运工单调队列优化DP简单题,和P2034重了题意:给定一行\(n\)个非负整数\(a_1\cdotsa_n\)。现在你可以选择其中若干个数,但不能有超过\(k\)个连续的数字被选择。你的任务是使得选出的数字的和最大。(直接抄的2034)正着考虑发现很麻烦,......