[loj3046]语言
定义$S_{i}$表示第$i$条链所包含的点的集合,$(x,y)$合法当且仅当$x\ne y$且$\exists i,\{x,y\}\subseteq S_{i}$(答案即$\frac{合法点对数}{2}$),显然后者等价于$y\in \cup_{x\in S_{i}}S_{i}$,因此合法点对数为$\sum_{x=1}^{n}|\cup_{x\in S_{i}}S_{i}|-1$
结论:$链并的大小=链端点所构成的虚树点数=\frac{按照dfs序排序后相邻(包括首尾)两点距离和}{2}+1$
前者显然,后者证明如下:
对每一条边统计经过次数,设其连结的深度较大的点为$x$,那么记$p_{i}=1$当且仅当$i$在$x$子树内(否则$p_{i}=0$),观察可得两个点$x$和$y$经过这条边当且仅当$p_{x}+p_{y}=1$
考虑dfs序的性质:每一个子树一定是一段区间,因此设端点按dfs序排序后为$a_{1},a_{2},...,a_{k}$,$S=\{i|p_{a_{i}}=1\}$一定是一段区间$[l,r]$,观察可得当$[l,r]=\emptyset$或$[l,r]=[1,k]$时该边答案为0,否则答案为2
考虑$[l,r]=\emptyset$或$[l,r]=[1,k]$的条件,即等价于这条边不在虚树上,那么$\frac{按照dfs序排序后相邻(包括首尾)两点距离和}{2}$即为边数,根据树的性质,加1即为点数
根据这个结论,将每条链差分并用线段树合并来找到所有端点,线段树上维护:1.个数(判断是否存在);2.区间最小点;3.区间最大点;4.区间相邻点距离和(最左和最右可以在外面算)即可,如果用st表维护lca可以做到$o(n\log_{2}n)$


1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define mid (l+r>>1)
5 struct ji{
6 int nex,to;
7 }edge[N<<1];
8 int V,E,n,m,x,y,head[N],dfn[N],id[N],s[N],f[N][21],r[N],ls[N*100],rs[N*100],vis[N*100],mn[N*100],mx[N*100],sum[N*100];
9 long long ans;
10 void add(int x,int y){
11 edge[E].nex=head[x];
12 edge[E].to=y;
13 head[x]=E++;
14 }
15 void dfs(int k,int fa,int sh){
16 dfn[k]=++x;
17 id[x]=k;
18 s[k]=sh;
19 f[k][0]=fa;
20 for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
21 for(int i=head[k];i!=-1;i=edge[i].nex)
22 if (edge[i].to!=fa)dfs(edge[i].to,k,sh+1);
23 }
24 int lca(int x,int y){
25 if (s[x]<s[y])swap(x,y);
26 for(int i=20;i>=0;i--)
27 if (s[f[x][i]]>=s[y])x=f[x][i];
28 if (x==y)return x;
29 for(int i=20;i>=0;i--)
30 if (f[x][i]!=f[y][i]){
31 x=f[x][i];
32 y=f[y][i];
33 }
34 return f[x][0];
35 }
36 int dis(int x,int y){
37 return s[x]+s[y]-2*s[lca(x,y)];
38 }
39 void up(int k){
40 mn[k]=min(mn[ls[k]],mn[rs[k]]);
41 mx[k]=max(mx[ls[k]],mx[rs[k]]);
42 sum[k]=sum[ls[k]]+sum[rs[k]];
43 if ((mx[ls[k]])&&(mn[rs[k]]<=n))sum[k]+=dis(id[mx[ls[k]]],id[mn[rs[k]]]);
44 }
45 void update(int &k,int l,int r,int x,int y){
46 if (!k){
47 k=++V;
48 mn[k]=n+1;
49 }
50 if (l==r){
51 vis[k]+=y;
52 if (vis[k]>0)mn[k]=mx[k]=l;
53 else{
54 mn[k]=n+1;
55 mx[k]=0;
56 }
57 return;
58 }
59 if (x<=mid)update(ls[k],l,mid,x,y);
60 else update(rs[k],mid+1,r,x,y);
61 up(k);
62 }
63 int merge(int k1,int k2){
64 if ((!k1)||(!k2))return k1+k2;
65 if ((!ls[k1])&&(!rs[k1])){
66 vis[k1]+=vis[k2];
67 if (vis[k1]>0){
68 mn[k1]=min(mn[k1],mn[k2]);
69 mx[k1]=max(mx[k1],mx[k2]);
70 }
71 else{
72 mn[k1]=n+1;
73 mx[k1]=0;
74 }
75 return k1;
76 }
77 ls[k1]=merge(ls[k1],ls[k2]);
78 rs[k1]=merge(rs[k1],rs[k2]);
79 up(k1);
80 return k1;
81 }
82 void dfs(int k,int fa){
83 for(int i=head[k];i!=-1;i=edge[i].nex)
84 if (edge[i].to!=fa){
85 dfs(edge[i].to,k);
86 r[k]=merge(r[k],r[edge[i].to]);
87 }
88 if (mn[r[k]]!=mx[r[k]])ans+=sum[r[k]]+dis(id[mn[r[k]]],id[mx[r[k]]]);
89 }
90 int main(){
91 scanf("%d%d",&n,&m);
92 memset(head,-1,sizeof(head));
93 for(int i=1;i<n;i++){
94 scanf("%d%d",&x,&y);
95 add(x,y);
96 add(y,x);
97 }
98 x=0;
99 dfs(1,0,1);
100 mn[0]=n+1;
101 for(int i=1;i<=m;i++){
102 scanf("%d%d",&x,&y);
103 int z=lca(x,y);
104 update(r[x],1,n,dfn[x],1);
105 update(r[x],1,n,dfn[y],1);
106 update(r[y],1,n,dfn[x],1);
107 update(r[y],1,n,dfn[y],1);
108 update(r[f[z][0]],1,n,dfn[x],-2);
109 update(r[f[z][0]],1,n,dfn[y],-2);
110 }
111 dfs(1,0);
112 printf("%lld",ans/4);
113 }
[loj3046]语言的更多相关文章
- [LOJ3046][ZJOI2019]语言:树链的并+线段树合并
分析 问题显然可以转化为对于每个节点询问所有这个节点的所有链的链并的大小. 考场上我直接通过树剖打标记+树剖线段树维护以\(O(n \log^3 n)\)的时间复杂度暴力实现了这个过程.(使用LCT或 ...
- bzoj5518 & loj3046 「ZJOI2019」语言 线段树合并+树链的并
题目传送门 https://loj.ac/problem/3046 题解 首先问题就是问有多少条路径是给定的几条路径中的一条的一个子段. 先考虑链的做法. 枚举右端点 \(i\),那么求出 \(j\) ...
- C语言 · 高精度加法
问题描述 输入两个整数a和b,输出这两个整数的和.a和b都不超过100位. 算法描述 由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储.对于这种问题,一般使用数组来处理. 定义一个数组A ...
- Windows server 2012 添加中文语言包(英文转为中文)(离线)
Windows server 2012 添加中文语言包(英文转为中文)(离线) 相关资料: 公司环境:亚马孙aws虚拟机 英文版Windows2012 中文SQL Server2012安装包,需要安装 ...
- iOS开发系列--Swift语言
概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...
- C语言 · Anagrams问题
问题描述 Anagrams指的是具有如下特性的两个单词:在这两个单词当中,每一个英文字母(不区分大小写)所出现的次数都是相同的.例如,"Unclear"和"Nuclear ...
- C语言 · 字符转对比
问题描述 给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一: 1:两个字符串长度不等.比如 Beijing 和 Hebei 2:两个字符串不仅长度相 ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Atitit 项目语言的选择 java c#.net php??
Atitit 项目语言的选择 java c#.net php?? 1.1. 编程语言与技术,应该使用开放式的目前流行的语言趋势1 1.2. 从个人职业生涯考虑,java优先1 1.3. 从项目实际来 ...
随机推荐
- 从零入门 Serverless | 教你 7 步快速构建 GitLab 持续集成环境
作者 | 存诚 阿里云弹性计算团队 本文整理自<Serverless 技术公开课>,"Serverless"公众号后台回复"入门",即可获取系列文章 ...
- SphereEx 公司成立,推动 Apache ShardingSphere 社区加速发展
近日,SphereEx 商业公司在中国红杉种子基金及初心资本助力下,已完成公司及团队组建.各大媒体平台及公众号已相继报道,并抢占新闻头条.作为以 Apache ShardingSphere 核心团队组 ...
- Windows用cmd编译运行Java程序
https://www.runoob.com/w3cnote/windows10-java-setup.html
- docker内服务访问宿主机服务
目录 1. 场景 2. 解决 4. 参考 1. 场景 使用windows, wsl2 进行日常开发测试工作. 但是wsl2经常会遇到网络问题.比如今天在测试一个项目,核心功能是将postgres 的数 ...
- 论文解读丨表格识别模型TableMaster
摘要:在此解决方案中把表格识别分成了四个部分:表格结构序列识别.文字检测.文字识别.单元格和文字框对齐.其中表格结构序列识别用到的模型是基于Master修改的,文字检测模型用到的是PSENet,文字识 ...
- 第四次Scrum Metting
日期:2021年4月29日 会议主要内容概述:交代近两日工作,进一步细化上次讨论细节,代码合并. 一.进度情况## 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 ...
- Intellij IDEA 2021.2.3 最新版免费激活教程(可激活至 2099 年,亲测有效)
申明,本教程 Intellij IDEA 最新版破解.激活码均收集与网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除.如条件允许,建议大家购买正版. 本教程更新于:2021 年 10 月 ...
- MIPI归纳---为什么阻抗为100欧姆
根据LVDS(Low Voltage Differential Signaling)电平定义的. LVDS差分信号PN两线最大幅度是350mV,内部一个恒流源电流是3.5mA.于是终端匹配电阻是100 ...
- Machine learning (6-Logistic Regression)
1.Classification However, 2.Hypothesis Representation Python code: import numpy as np def sigmoid(z) ...
- (类)Program1.1
1 class MyClass: 2 3 i = 12345 4 5 def __init__(self): 6 self.data = "WOOWOWOWO" 7 8 def f ...