【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;
}

转载于:https://www.cnblogs.com/cjyyb/p/11124994.html

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

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

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

  2. 树套树-线段树套平衡树

    作用 线段树的作用是区间修改和查询,平衡树的作用是查询第k大,k的排名,前驱,后继.这两个结合起来,就变成了可以区间修改和查询第k大,k的排名,前驱,后继的数据结构:树套树-线段树套平衡树. 实现 先 ...

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

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

  4. 线段树 ---- 线段树维护线段相加+滑动变长窗口 2021牛客多校第7场 F xay loves trees

    题目大意: 给你两个大小相同的树但是形状不一定一样 叫你选出最大的子集,满足下面两个条件 在第一颗树上是一条链 在第二颗树上任意两个点都不是祖先关系 解题思路: 首先我们现在第二颗树上面把每个点的df ...

  5. BZOJ 3685: 普通van Emde Boas树( 线段树 )

    建颗权值线段树就行了...连离散化都不用... 没加读入优化就TLE, 加了就A掉了...而且还快了接近1/4.... ---------------------------------------- ...

  6. 2021CCPC(桂林) - Suffix Automaton(后缀树+线段树)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串,再给出 qqq 次询问,每次询问需要输出本质不同第 kkk 小的子串的起止位置.如果有多个答案,输出起点最小的那个. 本题规定字符串大小 ...

  7. 牛客 - sequence(笛卡尔树+线段树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a 和数列 b ,求 题目分析:不算难的题目,对于每个 a[ i ] 求一下贡献然后维护最大值就好,具体思路就是,先找出每个 a[ i ] 左 ...

  8. HDU - 4417 Super Mario(主席树/线段树+离线)

    题目链接:点击查看 题目大意:给出由 n 个数的数列,再给出 m 次查询,每次查询需要输出 [ l , r ] 内小于等于 h 的数有多少个 题目分析:大晚上睡不着觉随便做做题,发现这个题目原来可以用 ...

  9. YbtOJ#752-最优分组【笛卡尔树,线段树】

    正题 题目链接:http://www.ybtoj.com.cn/problem/752 题目大意 nnn个人,每个人有cic_ici​和did_idi​分别表示这个人所在的队伍的最少/最多人数. 然后 ...

  10. P4755-Beautiful Pair【笛卡尔树,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4755 题目大意 nnn个数字的一个序列,求有多少个点对i,ji,ji,j满足ai×aj≤max{ak}(k∈[l ...

最新文章

  1. java9可执行jar_单个java文件打成可执行jar包
  2. IT行业老程序员的经验之谈:爬虫学到什么程度可以找到工作?
  3. 什么事情是你当了老板才知道的?
  4. spring aop 如何切面到mvc 的controller--转载
  5. MFC C++ 获取外网IP地址
  6. 电脑重启bootmgr_解决电脑开机出现bootmgr is compressed的两大妙招
  7. javascript学习之闭包
  8. TensorFlow 学习(七) — 常用函数 api、tf.nn、tf.keras
  9. pandas的dataframe
  10. android中所有颜色大全
  11. x86 x64 arm64的区别
  12. SpringBoot+Layui就业信息管理系统
  13. mysql添加索引报错1170 -BLOB/TEXT column ‘xx‘ used in key specification without a key length分析及解决
  14. Conky-colors详细教程
  15. unix/linux 系统 进程资源限制参数
  16. 1000行代码入门python-小白入门篇,Python到底是什么?
  17. 2021-02-04
  18. html5横竖条纹背景,CSS制作Web页面条纹背景样式的介绍
  19. 自动驾驶轨迹预测论文阅读(二)TPNet: Trajectory Proposal Network for Motion Prediction
  20. 由mouseover和mouseenter引发的思考

热门文章

  1. SQL Server 2005即将终止服务 你准备好了么?
  2. Factory模式与Prototype模式的异同
  3. updateStateByKey--word count
  4. Android 自定义ProgressDialog
  5. 点击按钮显示谷歌地图
  6. 巧妙设置Android来方便管理Linux和Windows
  7. F5 配置手册 -F5 BIG-IP 10.1-2-配置-基本参数
  8. 通过timer控件和窗体的opacity属性,轻松实现窗体的淡入淡出
  9. Taro -- 微信小程序登录
  10. html5中页面拨打电话的方式