正题

P6805


题目大意

给你一棵树,每次可选择两个叶子结点,然后覆盖路径上的边,代价为其长度,每个叶子结点只能选一次。

对于每次询问,加入若干新点(只会连接原树的点),问你覆盖所有边的最小代价。


解题思路

因为所有边都要覆盖,所以一个点至少连一条到父亲的边

不难发现,如果一个点的子树内有偶数各叶子结点,那么就要连出两条边,否则连一条边,因为所有点都要连向父亲,所以只计算多出来的

那么可以树链剖分,然后用线段树维护子树叶子结点的值

对于每次查询,相当于把若干链上的值异或1,然后查询整棵树的值


code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 100100
using namespace std;
int n,m,q,x,y,w,tot,a[N],s[N],h[N],p[N];
int sz[N],fa[N],hs[N],deg[N],low[N],dfn[N],dep[N],top[N],lsz[N];
struct rec
{int to,nx;
}e[N<<1];
void add(int x,int y)
{e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return;
}
struct Tree
{#define ls x*2#define rs x*2+1int v[N<<2],lazy[N<<2];void push_up(int x){v[x]=v[ls]+v[rs];return;}void get(int x,int l,int r){lazy[x]^=1;v[x]=r-l+1-v[x];return;}void push_down(int x,int l,int r){if(lazy[x]){int mid=l+r>>1;get(ls,l,mid);get(rs,mid+1,r);lazy[x]=0;}return;}void change(int x,int L,int R,int l,int r){if(L==l&&R==r){get(x,L,R);return;}push_down(x,L,R);int mid=L+R>>1;if(r<=mid)change(ls,L,mid,l,r);else if(l>mid)change(rs,mid+1,R,l,r);else change(ls,L,mid,l,mid),change(rs,mid+1,R,mid+1,r);push_up(x);return;}int ask(int x,int L,int R,int l,int r){if(L==l&&R==r)return v[x];push_down(x,L,R);int mid=L+R>>1;if(r<=mid)return ask(ls,L,mid,l,r);else if(l>mid)return ask(rs,mid+1,R,l,r);else return ask(ls,L,mid,l,mid)+ask(rs,mid+1,R,mid+1,r);}
}T;
void dfs1(int x)
{sz[x]=1;if(deg[x]==1)lsz[x]=1,p[x]=1;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y==fa[x])continue;fa[y]=x;dep[y]=dep[x]+1;dfs1(y);sz[x]+=sz[y];lsz[x]+=lsz[y];if(sz[y]>sz[hs[x]])hs[x]=y;}return;
}
void dfs2(int x,int anc)
{dfn[x]=++w;top[x]=anc;if(!(lsz[x]&1))T.change(1,1,n,dfn[x],dfn[x]);if(hs[x])dfs2(hs[x],anc);for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y==fa[x]||y==hs[x])continue;dfs2(y,y);}low[x]=w;return;
}
void add(int x)
{while(top[x]!=1){T.change(1,1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];}T.change(1,1,n,dfn[1],dfn[x]);return;
}
int main()
{scanf("%d%d",&n,&q);for(int i=1;i<n;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);deg[x]++;deg[y]++;}dep[1]=fa[1]=1;dfs1(1);dfs2(1,1);while(q--){scanf("%d",&m);for(int i=1;i<=m;++i){scanf("%d",&a[i]);s[i]=1;}a[m+1]=0;sort(a+1,a+1+m);for(int i=1;i<=m;++i)if(a[i]==a[i+1])s[i+1]+=s[i];else if(p[a[i]]){if(!(s[i]&1))add(a[i]);//修改一条链}else if(s[i]&1)add(a[i]);if(!T.ask(1,1,n,dfn[1],dfn[1]))puts("-1");//无法两两匹配else printf("%d\n",T.ask(1,1,n,dfn[1],low[1])+n+m-2);//加上没算的边,1没有连向父亲的边,但两边都会多算一次for(int i=1;i<=m;++i)if(a[i]!=a[i+1]){if(p[a[i]]){if(!(s[i]&1))add(a[i]);}else if(s[i]&1)add(a[i]);}}return 0;
}

【树链剖分】春季大扫除(P6805)相关推荐

  1. P6805-[CEOI2020]春季大扫除【贪心,树链剖分,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P6805 题目大意 给出nnn个点的一棵树,qqq次独立的询问.每次询问会在一些节点上新增一些子节点,然后你每次可以 ...

  2. 【模板】树链剖分 P3384

    题目链接 //部分转自:https://www.luogu.org/problemnew/solution/P3384 初学树链剖分,感觉这个模板题还是容易理解的,但是实在是码量很大的. 知识点: 重 ...

  3. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  4. bzoj1036: [ZJOI2008]树的统计Count 树链剖分

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从 ...

  5. 树链剖分 or 根号分治 + dfs序 + 树状数组 ---- CF1254 D. Tree Queries

    题目链接 题目大意: 问题转化: 很容易发现:假设修改的节点是vvv. 1.vvv的子树sonvson_vsonv​直接加上(n−size[sonv])n×d\frac{(n-size[son_v]) ...

  6. 树链剖分 + 后缀数组 - E. Misha and LCP on Tree

    E. Misha and LCP on Tree Problem's Link Mean: 给出一棵树,每个结点上有一个字母.每个询问给出两个路径,问这两个路径的串的最长公共前缀. analyse: ...

  7. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释...

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  8. [学习笔记]树链剖分

    基本思想 树链剖分一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每条边属于且只属于一条链,然后再通过数据结构来维护每一条链. 一些定义 树链:树上的路径. 剖分:把路径分类为重链和轻链 ...

  9. 树分治树链剖分相关题目讨论

    预备知识 树分治,树链剖分 poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs.c ...

最新文章

  1. 少侠,找个千手观音来帮你营销可好?
  2. 耳机使用说明书 jbl ua_用过JBL耳机后,才知道在运动领域BOSE和BO原来只是个弟弟...
  3. Python小游戏(俄罗斯方块)
  4. 微软超融合私有云测试08-SCVMM部署之SQL Server与前置条件安装
  5. 【bzoj4444】[Scoi2015]国旗计划 倍增
  6. 技术人员的明天:35岁后我们做什么
  7. 4.2 算法之数论 185 反正切函数的应用 python
  8. HTML 元素和属性--备份
  9. 查询排序_MySQL查询性能优化
  10. LTE TDD和FDD介绍
  11. windows上使用wordpress搭建博客
  12. 项目经验怎么写HTML,简历中的项目经验怎么写
  13. 《网络工程师 考前冲刺100题》思维导图
  14. one 主格 复数 宾格_主格和宾格
  15. 求1!+2!+3!+…+n!(2种方式)
  16. 基于Basys2的Booth乘法器的设计
  17. 理解 ES5, ES2015(ES6) 和 TypeScript
  18. SAP 委外加工与工序外协
  19. mysql中用来取余数的函数是_MySQL函数 练习题
  20. selenium 上传下载调用windows窗口--AutoIT

热门文章

  1. 信管专业c语言考什么,计算机信息管理专业卫生事业单位招聘考试笔试模拟题(十)...
  2. es6添加删除class_es6中class类的使用
  3. php判断子字符串位置,PHP怎样查询子字符串位置
  4. python根据列表绘制柱状图_python把一个列表画柱状图
  5. 35. 搜索插入位置011(二分查找)
  6. matlab调用时间序列工具箱,matlab时间序列工具箱
  7. [Spring5]IOC容器_Bean管理注解方式_完全注解开发
  8. [Java基础]字符流读写数据的方式
  9. LeetCode 543二叉树的直径-简单
  10. Observer(观察者)--对象行为型模式