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:果树——题解的更多相关文章

  1. HAOI2018 简要题解

    这套题是 dy, wearry 出的.学长好强啊,可惜都 \(wc\) 退役了.. 话说 wearry 真的是一个计数神仙..就没看到他计不出来的题...每次考他模拟赛总有一两道毒瘤计数TAT 上午的 ...

  2. BZOJ4009 & 洛谷3242 & LOJ2113:[HNOI2015]接水果——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4009 https://www.luogu.org/problemnew/show/P3242 ht ...

  3. ccf-csp201909题解

    目录 ccf-csp201909题解 1. 201909-1 小明种苹果 题目描述 解析 通过代码 2. 201909-2 小明种苹果(续) 题目描述 解析 通过代码 3. 201909-3 字符画 ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  8. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  9. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

随机推荐

  1. Linux命令应用大词典-第40章 网络客户端

    40.1 elinks:字符模式的Web浏览器 40.2 wget:从Web网站下载文件 40.3 curl:传输URL 40.4 lynx:通用分布式信息的万维网浏览器 40.5 lftp:实现文件 ...

  2. 给大家推荐:五个Python小项目,Github上的人气很高的

    1.深度学习框架 Pytorch https://github.com/pytorch/pytorch PyTorch 是一个 Torch7 团队开源的 Python 优先的深度学习框架,提供两个高级 ...

  3. java后台接收微信服务号/订阅号消息

    1.申请订阅号(适合个人)或者服务号(适合企业) 微信公众平台 2.填写配置 服务器地址: 需要接收消息 的服务端接口地址 令牌:通话识别码,随便写,后端接收时,使用一样的就可以了. 消息加密秘钥 : ...

  4. java 流 文件 IO

    Java 流(Stream).文件(File)和IO Java.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持很多种格式,比如:基本类 ...

  5. python数据分析基础——pandas Tutorial

    参考pandas官方文档: http://pandas.pydata.org/pandas-docs/stable/10min.html#min 1.pandas中的数据类型 Series 带有索引标 ...

  6. jetbrains系列激活

    没钱,只能DB了. 为了避免某些个人私自搭建服务器,以及自己搭建激活服务器,因此,决定使用破解包~~~. 注意:只要破解,就要屏蔽官方激活服务器:0.0.0.0 account.jetbrains.c ...

  7. python读取日志,存入mysql

    1.从 http://www.almhuette-raith.at/apache-log/access.log 下载 1万条日志记录,保存为一个文件,读取文件并解析日志,从日志中提取ip, time_ ...

  8. Tensorflow学习第1课——从本地加载MNIST以及FashionMNIST数据

    很多Tensorflow第一课的教程都是使用MNIST或者FashionMNIST数据集作为示例数据集,但是其给的例程基本都是从网络上用load_data函数直接加载,该函数封装程度比较高,如果网络出 ...

  9. Mysql-表和字段操作

    1.查看表 show tables; 2.创建表 create table test( id int primary key auto_increment, name varchar(40) not ...

  10. [mongodb]child process failed, exited with error number 100

    Run the following command first to start the mongo server mongod run --config /usr/local/etc/mongod. ...