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 ...
随机推荐
- 【JUC源码解析】Exchanger
简介 Exchanger,并发工具类,用于线程间的数据交换. 使用 两个线程,两个缓冲区,一个线程往一个缓冲区里面填数据,另一个线程从另一个缓冲区里面取数据.当填数据的线程将缓冲区填满时,或者取数据的 ...
- js函数相关高级用法
一.惰性载入函数(lazy function) 使用场景:当一个函数中的判断分支只用执行一次(第一次调用时执行),后续不会再变化,则可以使用惰性函数来提高性能. var addEvent = func ...
- 「日常训练」Card Game Cheater(HDU-1528)
题意与分析 题意是这样的:有\(n\)张牌,然后第一行是Adam的牌,第二行是Eve的牌:每两个字符代表一张牌,第一个字符表示牌的点数,第二个表示牌的花色.Adam和Eve每次从自己的牌中选出一张牌进 ...
- Consul 简介
Consul包含很多组件,总体来数,Consul是一种服务发现和配置工具. 服务发现:一个客户端提供自己的服务,例如api服务,或者mysql服务,另一个客户端就可以利用Consul通过DNS或者ht ...
- 了解Python控制流语句——continue 语句
continue 语句用以告诉 Python 跳过当前循环块中的剩余语句,并继续该循环的下一次迭代. 案例(保存为 continue.py): while True: s = input('Enter ...
- python3爬虫-快速入门-爬取图片和标题
直接上代码,先来个爬取豆瓣图片的,大致思路就是发送请求-得到响应数据-储存数据,原理的话可以先看看这个 https://www.cnblogs.com/sss4/p/7809821.html impo ...
- [堆+贪心]牛客练习赛40-B
传送门:牛客练习赛40 题面: 小A手头有 n 份任务,他可以以任意顺序完成这些任务,只有完成当前的任务后,他才能做下一个任务 第 i 个任务需要花费 x_i 的时间,同时完成第 i 个任务的时间不 ...
- Apache——访问控制
Order 指定执行允许访问规则和拒绝访问规则 Deny 定义拒绝访问列表 Allow 定义允许访问列表 Order allow,deny 先执行允许,再执行拒绝 Order deny,allow ...
- 基于MTCNN多任务级联卷积神经网络进行的人脸识别 世纪晟人脸检测
神经网络和深度学习目前为处理图像识别的许多问题提供了最佳解决方案,而基于MTCNN(多任务级联卷积神经网络)的人脸检测算法也解决了传统算法对环境要求高.人脸要求高.检测耗时高的弊端. 基于MTCNN多 ...
- 使用Python进行AES加密和解密
摘录于:http://blog.csdn.net/nurke/article/details/77267081 另外参考:http://www.cnblogs.com/kaituorensheng/p ...