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. katalon系列六:Katalon Studio Web UI关键字讲解

    在一个Test Case里,点左上Add-Web UI Keyword,可以添加一行新的命令. 像Click.setText.Delay这些最基本的,大家还是看看官方的API文档吧,望文知义,如果是纯 ...

  2. Kotlin的密封(Sealed)类:超强的枚举(KAD 28)

    作者:Antonio Leiva 时间:Jun 27, 2017 原文链接:https://antonioleiva.com/sealed-classes-kotlin/ Kotlin的封装类是Jav ...

  3. 第七模块:项目实战一 第1章 项目实战:CRM客户关系管理系统开发

    01-crm介绍 02-权限系统介绍 03-第一版表结构设计 04-第二版表结构设计 05-orm中创建表结构 06-销售管理系统业务 07-销售管理系统权限信息录入 08-快速实现简单的权限控制的设 ...

  4. Spring Cloud(八):配置中心(服务化与高可用)【Finchley 版】

    Spring Cloud(八):配置中心(服务化与高可用)[Finchley 版]  发表于 2018-04-19 |  更新于 2018-04-26 |  本文接之前的<Spring Clou ...

  5. 周期串 (Periodic Strings,UVa455)

    #include<stdio.h> #include<string.h> int main(void) { int n,stlen,i,j; ]; while(scanf(&q ...

  6. gossip版本raft算法实现

    raft算法的实现概述 节点的启动和加入: 1. 第一个节点启动,发现没有其他的member节点,则自己变成master 2. 第二个节点启动并加入第一个节点,发现有member节点,并且master ...

  7. Python3 标准库:calendar,time

    1.calendar import calendar print(calendar.month(2008,8)) #某个月 print(calendar.calendar(2008)) #某年 pri ...

  8. 业务迁移---redis

    以前也没怎么搞过redis 只知道他是一个nosql数据库很强大,这次迁移用到了~  正好熟练一下并记录过程,还挺繁琐.. 记录一下在学习中的几个问题,总结加深一下印象,有可能会漏掉或者有误差的地方~ ...

  9. 自测之Lesson14:多线程编程

    题目:创建一个线程,并理清主线程结束时会发生什么. 代码: #include <stdio.h> #include <pthread.h> #include <unist ...

  10. 互评Alpha版本——Thunder团队

    基于NABCD评论作品 Hello World! :http://www.cnblogs.com/120626fj/p/7807544.html 欢迎来怼 :http://www.cnblogs.co ...