正题

题目链接:https://www.luogu.com.cn/problem/P6805


题目大意

给出nnn个点的一棵树,qqq次独立的询问。每次询问会在一些节点上新增一些子节点,然后你每次可以选择两个为选择过的叶子节点然后覆盖它们的路径,要求在覆盖所有边的情况下使得每次的路径长度和最小。

1≤n,q,∑di≤1051\leq n,q,\sum d_i\leq 10^51≤n,q,∑di​≤105


解题思路

先考虑暴力怎么做,我们可以把所有叶子去掉然后每个点的权值就是它原来子节点中的叶子数。

然后由于一个节点之间的权值可以两两匹配,贪心的话一个节点只有可能有1/21/21/2条路径延伸到父节点,这样就可以统计了。

然后考虑多个询问如何处理,根据上面的方法,每条边只有可能统计1/21/21/2次,而统计两次时当且仅当子树内能够两两配对,此时因为不能有边没有覆盖,所以就只能拆开一个配对分两个上来。

具体地当一个点的子树中叶子数为偶数时它到其父节点的边会被统计两次。

这个用树链剖分维护即可。

时间复杂度:O(nlog⁡2n)O(n\log^2 n)O(nlog2n)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int N=1e5+10;
struct node{int to,next;
}a[N<<1];
int n,m,tot,cnt,ls[N],leaf[N],lsz[N];
int dep[N],fa[N],siz[N],son[N],top[N],id[N];
int w[N<<2],v[N<<2],lazy[N<<2];stack<int> s;
void Downdata(int x){if(!lazy[x])return;lazy[x*2]^=1;lazy[x*2+1]^=1;swap(w[x*2],v[x*2]);swap(w[x*2+1],v[x*2+1]);lazy[x]=0;return;
}
void Build(int x,int L,int R){if(L==R){w[x]=(L>1);return;}int mid=(L+R)>>1;Build(x*2,L,mid);Build(x*2+1,mid+1,R);w[x]=w[x*2]+w[x*2+1];
}
void Change(int x,int L,int R,int l,int r){if(L==l&&R==r){swap(w[x],v[x]);lazy[x]^=1;return;}int mid=(L+R)>>1;Downdata(x);if(r<=mid)Change(x*2,L,mid,l,r);else if(l>mid) Change(x*2+1,mid+1,R,l,r);else Change(x*2,L,mid,l,mid),Change(x*2+1,mid+1,R,mid+1,r);w[x]=w[x*2]+w[x*2+1];v[x]=v[x*2]+v[x*2+1];return;
}
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(int x){leaf[x]=(a[ls[x]].next==0);siz[x]=1;dep[x]=dep[fa[x]]+1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x])continue;fa[y]=x;dfs(y);lsz[x]+=lsz[y];siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}lsz[x]+=leaf[x];return;
}
void dfs2(int x){id[x]=++cnt;if(lsz[x]&1)Change(1,1,n,cnt,cnt); if(son[x]){top[son[x]]=top[x];dfs2(son[x]);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x]||y==son[x])continue;top[y]=y;dfs2(y);}return;
}
void Updata(int x){while(x){Change(1,1,n,id[top[x]],id[x]);x=fa[top[x]];}return;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}Build(1,1,n);dfs(1);top[1]=1;dfs2(1);while(m--){int k,x,sum=lsz[1];scanf("%d",&k);for(int i=1;i<=k;i++){scanf("%d",&x);if(leaf[x]==1)leaf[x]=2;else sum++,Updata(x);s.push(x);}if(sum&1)puts("-1");else printf("%d\n",n-1+k+w[1]);while(!s.empty()){int x=s.top();if(leaf[x]==2)leaf[x]=1;else Updata(x);s.pop();} }return 0;
}

P6805-[CEOI2020]春季大扫除【贪心,树链剖分,线段树】相关推荐

  1. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  2. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1153  Solved: 421 [Submit][Sta ...

  4. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  5. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  6. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...

  7. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  8. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. YbtOJ-染色计划【树链剖分,线段树,tarjan】

    正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai​,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...

最新文章

  1. css( div和span)——读书笔记
  2. Apple Pay,呸!
  3. centos静默安装oracle关于报错UnsatisfiedLinkError exception loading native library:njni10
  4. 带你了解FPGA(1)--一些需要了解的概念
  5. ElasticSearch核心基础之入门篇
  6. 【SpringMVC 笔记】Json 交互处理
  7. hadoop component summary
  8. IT项目管理之无休止会议
  9. c语言中学生信息管理系统中删除学生信息,学生信息管理系统C语言编程
  10. 21天学通C语言-学习笔记(8)
  11. k3金蝶 java版本_金蝶KIS旗舰版和K3wise的不同
  12. html5 左侧在线客服,在网页右侧漂浮的QQ在线客服代码,QQ在线状态代码(四种样式)...
  13. Xcode真机调试 could not lunch failed to get reply to handshake packet
  14. Android游戏:弹弹球(打砖块)
  15. IE,谷歌访问跨域问题
  16. 随着窗体大小变化改变控件的大小和字体
  17. android jetpack ViewModel 报错解决方法
  18. 竟然有删不了的文件夹?
  19. cubeIDE开发, stm32独立看门狗IWDG的CubeMX配置及HAL库底层实现分析
  20. 网站统计IP PV UV实现原理

热门文章

  1. linux cpu softirq,linux softirq机制
  2. 量子计算机设计理念和思路,课程的设计理念与思路
  3. centos php.ini redis,CentOS下安装Redis及Redis的PHP扩展
  4. java io操作_Java 的IO操作(文件的读,写操作)
  5. android 导航 美国,变美了 Android N或用全新虚拟导航按键
  6. 如何手动连上mysql_如何手动安装MySql
  7. 在服务器系统怎么设置地址怎么办,路由器怎么设置地址
  8. 机器学习——决策树学习
  9. 后端学习 - 并发编程
  10. 考研961数据结构c语言版真题,严蔚敏数据结构C语言版考研真题库