LOJ6276:果树——题解
https://loj.ac/problem/6276#submit_code
NiroBC 姐姐是个活泼的少女,她十分喜欢爬树,而她家门口正好有一棵果树,正好满足了她爬树的需求。
这颗果树有N 个节点,节点标号1……N。每个节点长着一个果子,第i 个节点上的果子颜色为Ci。
NiroBC 姐姐每天都要爬树,每天都要选择一条有趣的路径(u,v) 来爬。
一条路径被称作有趣的,当且仅当这条路径上的果子的颜色互不相同。
(u,v) 和(v,u) 被视作同一条路径。特殊地,(i,i) 也被视作一条路径,这条路径只含i 一个果子,显然是有趣的。
NiroBC 姐姐想知道这颗树上有多少条有趣的路径。
线段树好题(当然也很毒)。
考虑u和v同色时的不合法路径,分两种情况讨论:
1.u和v有一个不同于二者的lca
显然不合法路径的两端一个在u的子树中,一个在v的子树中。
2.v是u的祖先。
显然不合法路径的两端一个在u的子树中,一个在v的子树的补集(包括v)中。
同时我们用dfs序定义(u,v)为起点为u终点为v的路径,这样我们可以发现不合法路径的集合恰好围成了多个矩阵。
那么就是扫描线求矩形的并了(不会的话可以看POJ1389:Area of Simple Polygons),当然这是不合法路径,你需要取反后把对角线加上/2才行。
(PPPS:对角线的点显然不会属于任何一个矩形,且其统计的方法不能/2,故需要加上。)
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double dl;
const int N=1e5+;
const int B=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct path{
int to,nxt;
}e[N*];
struct node{
int x1,x2,y,w;
}edge[N*];
vector<int>c[N];
int n,cnt,head[N],pos[N],tot,num;
int anc[N][B+],dep[N],size[N];
ll tr[N*],lazy[N*];
inline bool cmp(node a,node b){
return a.y<b.y;
}
inline void add(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
inline int LCA(int i,int j){
if(dep[i]<dep[j])swap(i,j);
for(int k=B;k>=;k--)
if(dep[anc[i][k]]>=dep[j])i=anc[i][k];
if(i==j)return i;
for(int k=B;k>=;k--)
if(anc[i][k]!=anc[j][k])
i=anc[i][k],j=anc[j][k];
return anc[i][];
}
void dfs(int u){
pos[u]=++tot;size[u]=;
dep[u]=dep[anc[u][]]+;
for(int i=;i<=B;i++)
anc[u][i]=anc[anc[u][i-]][i-];
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v!=anc[u][]){
anc[v][]=u;
dfs(v);
size[u]+=size[v];
}
}
}
void ins(int a,int l,int r,int l1,int r1,int w){
if(r1<l||l1>r||l1>r1)return;
if(l1<=l&&r<=r1){
lazy[a]+=w;
if(lazy[a]>)tr[a]=r-l+;
else if(l==r)tr[a]=;
else tr[a]=tr[a*]+tr[a*+];
return;
}
int mid=(l+r)>>;
ins(a*,l,mid,l1,r1,w);ins(a*+,mid+,r,l1,r1,w);
if(!lazy[a])tr[a]=tr[a*]+tr[a*+];
}
int main(){
ll n=read();
for(int i=;i<=n;i++)c[read()].push_back(i);
for(int i=;i<n;i++){
int u=read(),v=read();
add(u,v);add(v,u);
}
dfs();
for(int i=;i<=n;i++){
for(int j=;j<c[i].size();j++){
for(int l=j+;l<c[i].size();l++){
int u=c[i][j],v=c[i][l];
int lca=LCA(u,v);
if(lca!=u&&lca!=v){
int x1=pos[u],y1=pos[v];
int x2=x1+size[u]-,y2=y1+size[v]-;
edge[++num]=(node){x1-,x2,y1,};
edge[++num]=(node){x1-,x2,y2+,-};
edge[++num]=(node){y1-,y2,x1,};
edge[++num]=(node){y1-,y2,x2+,-};
}else{
if(dep[u]>dep[v])swap(u,v);
int p=v;
for(int k=B;k>=;k--)
if(dep[anc[p][k]]>=dep[u]+)p=anc[p][k];
int x1=pos[p],y1=pos[v];
int x2=x1+size[p]-,y2=y1+size[v]-;
edge[++num]=(node){,x1-,y1,};
edge[++num]=(node){,x1-,y2+,-};
edge[++num]=(node){y1-,y2,,};
edge[++num]=(node){y1-,y2,x1,-}; edge[++num]=(node){x2,n,y1,};
edge[++num]=(node){x2,n,y2+,-};
edge[++num]=(node){y1-,y2,x2+,};
edge[++num]=(node){y1-,y2,n+,-};
}
}
}
}
ll ans=;
sort(edge+,edge+num+,cmp);
ins(,,n,edge[].x1+,edge[].x2,edge[].w);
for(int i=;i<=num;i++){
ll h=edge[i].y-edge[i-].y;
ans+=h*tr[];
ins(,,n,edge[i].x1+,edge[i].x2,edge[i].w);
}
printf("%lld\n",(n*(n+)-ans)>>);
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
LOJ6276:果树——题解的更多相关文章
- HAOI2018 简要题解
这套题是 dy, wearry 出的.学长好强啊,可惜都 \(wc\) 退役了.. 话说 wearry 真的是一个计数神仙..就没看到他计不出来的题...每次考他模拟赛总有一两道毒瘤计数TAT 上午的 ...
- BZOJ4009 & 洛谷3242 & LOJ2113:[HNOI2015]接水果——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4009 https://www.luogu.org/problemnew/show/P3242 ht ...
- ccf-csp201909题解
目录 ccf-csp201909题解 1. 201909-1 小明种苹果 题目描述 解析 通过代码 2. 201909-2 小明种苹果(续) 题目描述 解析 通过代码 3. 201909-3 字符画 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
随机推荐
- Net Core学习笔记
Net Core 官网:https://dotnet.github.io/ Net Core Api: https://docs.microsoft.com/en-us/dotnet/api/?vie ...
- MVC数据的注册及验证简单总结
一.注解 注解是一种通用机制,可以用来向框架注入元数据,同时,框架不只驱动元数据的验证,还可以在生成显示和编辑模型的HTML标记时使用元数据. 二.验证注册的使用 1.Require:属性为Null或 ...
- Struts2(十.在修改页显示照片列表并增加删除照片功能)
一.显示照片列表功能 struts2中一般的处理方式:先在action中,准备数据,转到jsp中显示 1.UserAction /** * 点击修改用户按钮跳转到修改用户界面 * 为用户准备照片,以便 ...
- lintcode433 岛屿的个数
岛屿的个数 给一个01矩阵,求不同的岛屿的个数. 0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右为相邻. 您在真实的面试中是否遇到过这个题? Yes 样例 在矩阵: ...
- (原) MaterialEditor部- UmateriaEditor中 Node编译过程和使用(3)修正
@author: 白袍小道 转载说明原处,爱护劳动 插件同步在GITHUB: DaoZhang_XDZ 说明 1.本篇是接着-----(原) MaterialEditor部- Umat ...
- 查找 二叉树中 k1 到 k2区间的节点
vector<int> res; int key1, key2; void traverse(TreeNode * root){//采用前序遍历 if(root == NULL) retu ...
- SpringCloud IDEA 教学 (四) 断路器(Hystrix)
写在开始 在SpringCloud项目中,服务之间相互调用(RPC Remote Procedure Call —远程过程调用),处于调用链路底层的服务产生不可用情况时,请求会产生堆积使得服务器线程阻 ...
- 4.安装hive
下载安装包并解压安装元数据库配置hive添加hvie环境变量修改hive-env.sh修改hive配置文件初始化metastore使用hive cli配置hivemestore配置hiveserv ...
- POJ 3415 Common Substrings(后缀数组)
Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given t ...
- Python函数的内省-Introspection
Python函数可以进行内省-Introspection,查看函数内部的细节,方式就是使用函数的__code__属性. def func(a, b = 2): return a + b >> ...