【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. 【centOS】centOS7 下载

    地址:http://mirrors.aliyun.com/centos/ 进入国内的阿里云的,这里CentOS 7提供了三种ISO镜像文件的下载:DVD ISO.Everything ISO.Mini ...

  2. 自定义Visual Studio调试器中的对象显示方式

    你有没有盯着调试器窗口中的对象,并希望你可以通过其他类型的东西来查看这些对象?我当然有!扩展项目以确定每个人的身份可能会非常快速.理想情况下,通过特定的属性值快速定位它们会很棒.对我们来说幸运的是,V ...

  3. C# - VS2019页面布局容器splitContainer和groupBox小结

    前言 在WinFrm应用程序中,产品的外观.布局将直接影响用户第一体验,所以对于开发者来说,在没有美工支持的前提下,应当注意系统页面的布局,本章主要讲解splitContainer和groupBox的 ...

  4. Promise简单使用,需要在ES6以上

     //Promise延时顺序执行 var waitOne = new Promise(function(resolve, reject) { setTimeout(function(){ resolv ...

  5. 关于在 ASP.NET 的 Global.asax 中 Application_Error 方法内,设置跳转到自定义错误页无效的问题

    转自:https://www.cnblogs.com/OpenCoder/p/5070645.html 在 Global.asax 中的 Application_Error 方法中,使用 Respon ...

  6. Android 布局测试

    wrap_content <Button android:id="@+id/button1" android:layout_width="wrap_content& ...

  7. [转]Eclipse插件开发之基础篇(1) 插件开发的基础知识

    原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/08/13/eclipse_plugin_1_0_2.html 名词翻译 有一些名词在翻译的过程中可能 ...

  8. RAID5的创建(5块磁盘,三块做raid,两块做备份)

    RAID5的创建(5块磁盘,三块做raid,两块做备份) 第一步:参考我的上一篇博客,用同样的方法添加5块硬盘.地址如下: https://www.cnblogs.com/Feng-L/p/11735 ...

  9. 【bzoj1941】[Sdoi2010]Hide and Seek(kd-tree)

    bzoj 题意: 给出\(n\)个点,对于每个点,\(d_i\)等于距离其最远的点的距离减去距离最近的点的距离.这里的距离为曼哈顿距离. 求\(min\{d_i\}\). 思路: 考虑直接对每个点暴力 ...

  10. web-神盾局的秘密

    题目地址 http://web.jarvisoj.com:32768/ 首页是一张图片 查看源码,看到了一些猫腻,showing.php     c2hpZWxkLmpwZw==是base64编码   ...