【UOJ#388】【UNR#3】配对树(线段树,dsu on tree)

题面

UOJ

题解

考虑一个固定区间怎么计算答案,把这些点搞下来建树,然后\(dp\),不难发现一个点如果子树内能够匹配的话就一定会匹配完,所以\(dp\)可以做到线性。

那么根据上面的\(dp\)方式,一条边会被匹配到,当且仅当把这条边删掉之后,两个连通块内分别有奇数个目标点。那么如果我们考虑枚举每一条边,然后把子树内的点给标记一下,于是变成了在原序列上求有多少个偶数区间满足有偶数个点被标记,这个问题可以做一个前缀和,把奇偶位置拆开,于是答案就是两个位置中的奇数个数乘上偶数个数。这个过程可以拿线段树维护。

接下来就变成每次要标记子树中的所有点,每次暴力显然不合理。

改成\(dsu\)这个复杂度就很合理了。这个复杂度似乎是两个\(log\)的。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define MAX 100100
#define MOD 998244353
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,ans;
struct Line{int v,next,w;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
int wf[MAX],sz[MAX],hson[MAX];
void dfs1(int u,int ff)
{
sz[u]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
wf[v]=e[i].w;dfs1(v,u);sz[u]+=sz[v];
if(sz[v]>sz[hson[u]])hson[u]=v;
}
}
#define lson (now<<1)
#define rson (now<<1|1)
struct Node{int s[2][2],r;}t[MAX<<2];
void pushup(int now)
{
t[now].s[0][0]=(t[lson].s[0][0]+t[rson].s[0][0])%MOD;
t[now].s[0][1]=(t[lson].s[0][1]+t[rson].s[0][1])%MOD;
t[now].s[1][0]=(t[lson].s[1][0]+t[rson].s[1][0])%MOD;
t[now].s[1][1]=(t[lson].s[1][1]+t[rson].s[1][1])%MOD;
}
void Build(int now,int l,int r)
{
if(l==r){t[now].s[l&1][0]+=1;return;}
int mid=(l+r)>>1;
Build(lson,l,mid);
Build(rson,mid+1,r);
pushup(now);
}
void putrev(int now)
{
swap(t[now].s[0][0],t[now].s[0][1]);
swap(t[now].s[1][0],t[now].s[1][1]);
t[now].r^=1;
}
void pushdown(int now)
{
if(!t[now].r)return;
putrev(lson);putrev(rson);
t[now].r^=1;
}
void Modify(int now,int l,int r,int L,int R)
{
if(L<=l&&r<=R){putrev(now);return;}
int mid=(l+r)>>1;pushdown(now);
if(L<=mid)Modify(lson,l,mid,L,R);
if(R>mid)Modify(rson,mid+1,r,L,R);
pushup(now);
}
vector<int> V[MAX];
bool vis[MAX];
void upd(int u,int ff)
{
for(int v:V[u])Modify(1,0,m,v,m);
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff&&!vis[e[i].v])upd(e[i].v,u);
}
void dfs(int u,int ff,int tp)
{
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff&&e[i].v!=hson[u])
dfs(e[i].v,u,0);
if(hson[u])dfs(hson[u],u,1),vis[hson[u]]=true;
upd(u,ff);
int cnt=(1ll*t[1].s[0][0]*t[1].s[0][1]+1ll*t[1].s[1][0]*t[1].s[1][1])%MOD;
ans=(ans+1ll*cnt*wf[u])%MOD;
vis[hson[u]]=false;
if(!tp)upd(u,ff);
}
int main()
{
n=read();m=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read(),w=read();
Add(u,v,w);Add(v,u,w);
}
for(int i=1;i<=m;++i)V[read()].push_back(i);
Build(1,0,m);dfs1(1,0);dfs(1,0,0);
printf("%d\n",ans);
return 0;
}

【UOJ#388】【UNR#3】配对树(线段树,dsu on tree)的更多相关文章

  1. UOJ #164 [清华集训2015]V (线段树)

    题目链接 http://uoj.ac/problem/164 题解 神仙线段树题. 首先赋值操作可以等价于减掉正无穷再加上\(x\). 假设某个位置从前到后的操作序列是: \(x_1,x_2,..., ...

  2. 浅谈树套树(线段树套平衡树)&学习笔记

    0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...

  3. [UOJ UNR#1]奇怪的线段树

    来自FallDream的博客,未经允许,请勿转载, 谢谢. 原题可以到UOJ看,传送门 如果存在一个点是白的,却有儿子是黑的,显然无解. 不然的话,只要所有黑色的“黑叶子”节点,即没有黑色的儿子的节点 ...

  4. UOJ#7. 【NOI2014】购票 | 线段树 凸包优化DP

    题目链接 UOJ #7 题解 首先这一定是DP!可以写出: \[f[i] = \min_{ancestor\ j} \{f[j] + (d[j] - d[i]) * p[i] + q[i]\}\] 其 ...

  5. UOJ #314. 【NOI2017】整数 | 线段树 压位

    题目链接 UOJ 134 题解 可爱的电音之王松松松出的题--好妙啊. 首先想一个朴素的做法! 把当前的整数的二进制当作01序列用线段树维护一下(序列的第i位就是整数中位权为\(2^k\)的那一位). ...

  6. 【uoj#228】基础数据结构练习题 线段树+均摊分析

    题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有三种:区间加.区间开根.区间求和. $n,m,a_i\le 100000$ . 题解 线段树+均摊分析 对于原来的两个数 $a$ ...

  7. UOJ#470. 【ZJOI2019】语言 虚树,线段树合并

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ470.html 前言 做完情报中心来看这个题突然发现两题有相似之处然后就会做了. 题解 首先,我们考虑将所有答案点对分为两 ...

  8. UOJ#299. 【CTSC2017】游戏 线段树 概率期望 矩阵

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ299.html 前言 不会概率题的菜鸡博主做了一道概率题. 写完发现运行效率榜上的人都没有用心卡常数——矩阵怎么可以用数组 ...

  9. UOJ#467. 【ZJOI2019】线段树 线段树,概率期望

    原文链接www.cnblogs.com/zhouzhendong/p/ZJOI2019Day1T2.html 前言 在LOJ交了一下我的代码,发现它比选手机快将近 4 倍. 题解 对于线段树上每一个节 ...

  10. 【BZOJ-3306】树 线段树 + DFS序

    3306: 树 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 792  Solved: 262[Submit][Status][Discuss] De ...

随机推荐

  1. [ida]查看某一函数在程序中被谁引用

    1. 点亮函数名 2.view - open subviews - cross references 注意:不要点击绘图那个

  2. SpringCloud的入门学习之Eureka(Eureka的单节点)

    SpringCloud--->Spring生态体系的微服务架构:https://spring.io/ 官网贴图,如下所示,介绍了微服务的架构体系(话说,英语好读官网,可能很爽吧,没体验过). 1 ...

  3. Nginx反向代理Tomcat静态资源无法加载以及请求链接错误

     在使用Nginx实现Tomcat的负载均衡的时候,项目发布到了Tomcat,Nginx也配置好了, 当访问的时候发现了与预期不符 表现为: 静态资源加载失败 链接跳转地址错误 下面是我错误的配置文件 ...

  4. Thread之模板模式

    我们知道,在实际使用线程的时候,真正的执行逻辑都是写在run方法里面,run方法是线程的执行单元,如果我们直接使用Thread类实现多线程,那么run方法本身就是一个空的实现,如下: /** * If ...

  5. 【LeetCode】746. 使用最小花费爬楼梯

    使用最小花费爬楼梯 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始). 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或 ...

  6. jQuery—自定义HTTP请求

    Ajax设置自定义请求头的两种方法 $.ajax({ url: 'http://www.baidu.com', type: 'get', data: JSON.stringify({"nam ...

  7. [Linux] 解决nginx: [emerg] directive "rewrite" is not terminated by ";"

    解决nginx: [emerg] directive "rewrite" is not terminated by ";"nginx的rewite规则有时候没注 ...

  8. 分布式系统ID的几种生成办法

    前言 一般单机或者单数据库的项目可能规模比较小,适应的场景也比较有限,平台的访问量和业务量都较小,业务ID的生成方式比较原始但是够用,它并没有给这样的系统带来问题和瓶颈,所以这种情况下我们并没有对此给 ...

  9. 谷歌浏览器安装JsonView插件

    可方便阅读json格式文件,参考https://www.jianshu.com/p/6ea9f2245f4d

  10. Html学习之一(锚点链接的使用,页面间的跳转)

    页面一: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...