原题传送门

看到这种树上统计点对个数的题一般是线段树合并,这题也不出意外

先对这棵树进行树剖,对于每次普及语言,在\(x,y\)两点的线段树上的\(x,y\)两位置打\(+1\)标记,在点\(fa[lca(x,y)]\)的线段树上\(x,y\)两位置打\(-2\)标记

线段树中该维护三个东西:

1.dfs序最小的\(lp\)

2.dfs序最大的\(rp\)

3.线段树中所有被打标机的点到根节点路径的并的节点个数\(sum\)

我们进行搜索并从下向上的进行线段树合并,对于每个节点,对答案的贡献就是该节点线段树的根节点的\(sum-dep[lca(lp,rp)]+1-1\)(珂以画图理解一下)

交上去,发现wa了,因为每条路径的贡献被我们算了\(2\)次,所以除以2即可

#include <bits/stdc++.h>
#define N 100005
#define ll long long
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register ll x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int n,m;
ll ans;
struct edge{
int to,next;
}e[N<<1];
int head[N],cnt=0;
inline void add(register int u,register int v)
{
e[++cnt]=(edge){v,head[u]};
head[u]=cnt;
}
int size[N],fa[N],son[N],dep[N],top[N],dfn[N],tim,idfn[N];
inline void dfs1(register int x)
{
size[x]=1;
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x])
continue;
dep[v]=dep[x]+1;
fa[v]=x;
dfs1(v);
size[x]+=size[v];
if(size[v]>size[son[x]])
son[x]=v;
}
}
inline void dfs2(register int x,register int t)
{
dfn[x]=++tim;
idfn[tim]=x;
top[x]=t;
if(son[x])
dfs2(son[x],t);
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa[x]&&v!=son[x])
dfs2(v,v);
}
}
inline int getlca(register int x,register int y)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy])
{
x^=y^=x^=y;
fx^=fy^=fx^=fy;
}
x=fa[fx];
fx=top[x];
}
return dep[x]<dep[y]?x:y;
}
int root[N],tot;
struct node{
int ls,rs,cnt,lp,rp,sum;
}tr[N*60];
inline void pushup(register int x)
{
tr[x].lp=tr[tr[x].ls].lp?tr[tr[x].ls].lp:tr[tr[x].rs].lp;
tr[x].rp=tr[tr[x].rs].rp?tr[tr[x].rs].rp:tr[tr[x].ls].rp;
tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum;
if(tr[tr[x].ls].rp&&tr[tr[x].rs].lp)
tr[x].sum-=dep[getlca(tr[tr[x].ls].rp,tr[tr[x].rs].lp)];
}
inline void modify(register int &x,register int l,register int r,register int pos,register int val)
{
if(!x)
x=++tot;
if(l==r)
{
tr[x].cnt+=val;
if(tr[x].cnt)
tr[x].lp=tr[x].rp=pos,tr[x].sum=dep[pos];
else
tr[x].lp=tr[x].rp=tr[x].sum=0;
return;
}
int mid=l+r>>1;
if(dfn[pos]<=mid)
modify(tr[x].ls,l,mid,pos,val);
else
modify(tr[x].rs,mid+1,r,pos,val);
pushup(x);
}
inline void merge(register int &a,register int b,register int l,register int r)
{
if(!a||!b)
{
a=a+b;
return;
}
if(l==r)
{
tr[a].cnt+=tr[b].cnt;
if(tr[a].cnt)
tr[a].lp=tr[a].rp=idfn[l],tr[a].sum=dep[idfn[l]];
else
tr[a].lp=tr[a].rp=tr[a].sum=0;
return;
}
int mid=l+r>>1;
merge(tr[a].ls,tr[b].ls,l,mid);
merge(tr[a].rs,tr[b].rs,mid+1,r);
pushup(a);
}
inline void dfs(register int x)
{
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x])
continue;
dfs(v);
merge(root[x],root[v],1,tim);
}
if(tr[root[x]].lp&&tr[root[x]].rp)
ans+=tr[root[x]].sum-dep[getlca(tr[root[x]].lp,tr[root[x]].rp)];
}
int main()
{
n=read(),m=read();
for(register int i=1;i<n;++i)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs1(1);
dfs2(1,0);
for(register int i=1;i<=m;++i)
{
int x=read(),y=read();
int lca=getlca(x,y);
modify(root[x],1,tim,x,1);
modify(root[x],1,tim,y,1);
modify(root[y],1,tim,x,1);
modify(root[y],1,tim,y,1);
if(lca>1)
{
modify(root[fa[lca]],1,tim,x,-2);
modify(root[fa[lca]],1,tim,y,-2);
}
}
dfs(1);
write(ans>>1);
return 0;
}

【题解】Luogu P5327 [ZJOI2019]语言的更多相关文章

  1. Luogu P5327 [ZJOI2019]语言

    ZJOI2019Day2的温暖题,然后考场上只会大常数的\(O(n\log^3 n)\),就懒得写拿了60pts走人 首先我们简化题意,容易发现每个点能到达的点形成了一个联通块,我们只需要统计出这个联 ...

  2. 题解 P5327 [ZJOI2019]语言

    P5327 [ZJOI2019]语言 解题思路 暴力 首先讲一下我垃圾的 40pts 的暴力(其他 dalao 都是 60pts 起步): 当然评测机快的话(比如 LOJ 的),可以卡过 3,4 个点 ...

  3. P5327 [ZJOI2019]语言

    一边写草稿一边做题吧.要看题解的往下翻,或者是旁边的导航跳一下. 草稿 因为可以开展贸易活动的条件是存在一种通用语 \(L\) 满足 \(u_i\) 到 \(v_i\) 的最短路径上都会 \(L\) ...

  4. [题解] Luogu P5446 [THUPC2018]绿绿和串串

    [题解] Luogu P5446 [THUPC2018]绿绿和串串 ·题目大意 定义一个翻转操作\(f(S_n)\),表示对于一个字符串\(S_n\), 有\(f(S)= \{S_1,S_2,..., ...

  5. 【题解】Luogu P5279 [ZJOI2019]麻将

    原题传送门 希望这题不会让你对麻将的热爱消失殆尽 我们珂以统计每种牌出现的次数,不需要统计是第几张牌 判一副牌能不能和,类似这道题 对于这题: 设\(f[i][j][k][0/1]\)表示前\(i\) ...

  6. 【题解】Luogu P5328 [ZJOI2019]浙江省选

    原题传送门 看起来挺妙实际很暴力的一题 已知每个选手的分数都是平面上的直线 题目实际就是让我们求每条直线在整点处最大是第几大 我们考虑先对所有的直线进行半平面交(因为\(a_i\)都是正整数,所以比普 ...

  7. 题解 [ZJOI2019]语言

    题目传送门 题目大意 给出一个 \(n\) 个点的树,现在有 \(m\) 次操作,每次可以选择一个链 \(s,t\),,然后这条链上每个点都会增加一个相同属性,问对于每一个点有与它相同属性的有多少个点 ...

  8. 题解 Luogu P2499: [SDOI2012]象棋

    关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可 ...

  9. Luogu P5279 [ZJOI2019]麻将

    ZJOI2019神题,间接送我退役的神题233 考场上由于T2写挂去写爆搜的时候已经没多少时间了,所以就写挂了233 这里不多废话直接开始讲正解吧,我们把算法分成两部分 1.建一个"胡牌自动 ...

随机推荐

  1. android studio学习----添加项目依赖包总结

    Gradle Library Projects Gradle 项目可以依赖于其它组件.这些组件可以是外部二进制包,或者是其它的 Gradle 项目. 在本例中, app/build.gradle 中有 ...

  2. Android源码分析(九)-----如何修改Android系统默认时间

    一 : 修改Android系统默认时间 源码路径:frameworks/base/services/java/com/android/server/SystemServer.java 主要变量EARL ...

  3. java mybatis Column 'AAA' in where clause is ambiguous

    今天在java mybatis项目中遇到一个问题,“java mybatis Column 'AAA' in where clause is ambiguous”, 这是由于在多表连接查询的时候,遇上 ...

  4. nginx 日志问题(\x22)

    nginx 日志问题(\x22) 问题: 1.request_body中含有中文时,nginx日志会转换为十六进制. 2.nginx记录问题 POST /xxxxx HTTP/1.1|200|4266 ...

  5. maven中,dependency 中的 classifier属性

    classifier元素用来帮助定义构件输出的一些附属构件.附属构件与主构件对应,比如主构件是 kimi-app-2.0.0.jar 该项目可能还会通过使用一些插件生成 如 kimi-app-2.0. ...

  6. 单文件WebUploader做大文件的分块和断点续传

    前言: WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流 ...

  7. 洛谷P1192-台阶问题(线性递推 扩展斐波那契)

    占坑 先贴上AC代码 回头来补坑 #include <iostream> using namespace std; int n, k; const int mod = 100003; lo ...

  8. Java多线程编程核心技术-第6章-单例模式与多线程-读书笔记

    第 6 章 单例模式与多线程 本章主要内容 如何使单例模式遇到多线程是安全的.正确的. 6.1 立即加载 / “饿汉模式” 什么是立即加载?立即加载就是使用类的时候已经将对象创建完毕,常见的实现办法就 ...

  9. crystalreport使用方法

    使用: 打开CrystalReport官网下载页 目前最新版本为13.0.4 选择“SAP Crystal Reports, version for Visual Studio 2010 - Stan ...

  10. Anaconda3(5-2)程序编辑器 win10下PyCharm安装及配置Pytorch流程

    由于破解和付费问题,不推荐.优先用自带的spyder Win10 下PyCharm安装流程:(1)官网:https://www.jetbrains.com/pycharm/download/#sect ...