题目地址:https://oj.neu.edu.cn/problem/1204

题目大意:

其实就是树上的线段覆盖,

给出一棵n个结点的树,然后给出树上的一些路径进行覆盖,然后要求选取最少的点,能够把这些线段都占有

(或者说:一开始树上每个结点权值都为0,选取最少的点,把它们的权重变成1,使得询问的每一条路径上有含有权值为1的结点)

题解:

类似线段覆盖(线段覆盖是按照右端点贪心)

这个题就是按照每个路径的lca的深度贪心

也就是说把询问按照lca的深度从大到小排序

然后依次枚举询问

如果当前询问的路径没有权值为1的结点,就把lca赋值成1,答案加1

如果有就跳过

最后输出就可以了

整个过程用树链剖分就可以维护

(第一次wa是没有多组输入输出,第二次wa是把return 0 放在多组数据里了,第三次wa是忘记删freopen。。。orz)

#include <algorithm>
#include <cstring>
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e5 + ;
const int maxm = 5e5 + ;
int tree[maxn*], deep[maxn], p[maxn], sz[maxn], son[maxn], top[maxn], F[maxn];
int tot = ;
vector<int> G[maxn];
struct Que{
int x, y, lca;
bool operator <(const Que& B) const{
return deep[lca] < deep[B.lca];
}
};
vector<Que> Q;
void Insert(int o, int l, int r, int k, int v){
if(l == r) { tree[o] = v; return; }
int mid = (l+r)>>;
if(k <= mid) Insert(o*, l, mid, k, v);
else Insert(o*+, mid+, r, k, v);
tree[o] = max(tree[o*], tree[o*+]);
}
int Query(int o, int l, int r, int L, int R){
if(L <= l && r <= R) return tree[o];
int mid = (l+r)>>, ans = ;
if(L <= mid) ans = max(ans, Query(o*, l, mid, L, R));
if(R > mid) ans = max(ans, Query(o*+, mid+, r, L, R));
return ans;
} int dfs1(int x, int fa, int d){
deep[x] = d;
p[x] = fa;
sz[x] = ;
for(auto to : G[x]){
if(fa == to) continue;
sz[x] += dfs1(to, x, d+);
if(sz[to] > sz[son[x]]) son[x] = to;
}
return sz[x];
}
void dfs2(int x, int fa){
F[x] = ++tot;
if(son[fa] == x) top[x] = top[fa];
else top[x] = x;
if(son[x]) dfs2(son[x], x);
for(auto to : G[x]){
if(to == fa || to == son[x]) continue;
dfs2(to, x);
}
}
int TQuery(int x, int y, int &lca){
int ans = ;
while(top[x] != top[y]){
if(deep[top[y]] > deep[top[x]]) swap(x, y);
ans = max(ans, Query(, , tot, F[top[x]], F[x]));
x = p[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
ans = max(ans, Query(, , tot, F[x], F[y]));
lca = x;
return ans;
} int main()
{ int n, m, x, y;
while(cin>>n){
tot = ;
for(int i = ; i <= n; i++) G[i].clear();
memset(son, , sizeof(son));
memset(tree, , sizeof(tree));
for(int i = ; i <= n; i++){
scanf("%d %d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs1(, , );
dfs2(, );
cin>>m;
Q.resize(m);
for(int i = ; i < m; i++){
scanf("%d %d", &Q[i].x, &Q[i].y);
TQuery(Q[i].x, Q[i].y, Q[i].lca);
}
sort(Q.begin(), Q.end());
reverse(Q.begin(), Q.end());
int ans = ;
for(auto a : Q){
int k = TQuery(a.x, a.y, a.lca);
if(k) continue;
else Insert(, , tot, F[a.lca], ), ans++;
}
cout<<ans<<endl;
}
return ;
}

2017博普杯 东北大学邀请赛(B. Drink too much water)(贪心+树链剖分)的更多相关文章

  1. 树链剖分的一种妙用与一类树链修改单点查询问题的时间复杂度优化——2018ACM陕西邀请赛J题

    题目描述 有一棵树,每个结点有一个灯(初始均是关着的).每个灯能对该位置和相邻结点贡献1的亮度.现有两种操作: (1)将一条链上的灯状态翻转,开变关.关变开: (2)查询一个结点的亮度. 数据规模:\ ...

  2. loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)

    题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...

  3. 2019 icpc南昌全国邀请赛-网络选拔赛J题 树链剖分+离线询问

    链接:https://nanti.jisuanke.com/t/38229 题意: 给一棵树,多次查询,每次查询两点之间权值<=k的边个数 题解: 离线询问,树链剖分后bit维护有贡献的位置即可 ...

  4. 主席树+树链剖分——南昌邀请赛Distance on the tree

    学了差不多一星期的主席树+树链剖分,再来看这题发现其实是个板子题 一开始想复杂了,以为要用类似求树上第k大的树上差分思想来解决这道题,但其实树链上<=k的元素个数其实直接可以用树链剖分来求 具体 ...

  5. 2019南昌邀请赛网络预选赛 J.Distance on the tree(树链剖分)

    传送门 题意: 给出一棵树,每条边都有权值: 给出 m 次询问,每次询问有三个参数 u,v,w ,求节点 u 与节点 v 之间权值 ≤ w 的路径个数: 题解: 昨天再打比赛的时候,中途,凯少和我说, ...

  6. LOJ.6073.[2017山东一轮集训Day5]距离(可持久化线段树 树链剖分)

    题目链接 就是恶心人的,简单写写了...(似乎就是[HNOI2015]开店?) 拆式子,记\(dis_i\)为\(i\)到根节点的路径权值和,\(Ans=\sum dis_{p_i}+\sum dis ...

  7. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  8. 2019 ACM-ICPC 西安全国邀请赛 E-Tree 树链剖分+线段树

    题意 给一颗带点权的树,三种操作 \(1~s~t\) 修改从1到s的路径上的所有点,\(a[i]=a[i]|t\) \(2~s~t\) 修改从1到s的路径上的所有点,\(a[i]=a[i]\& ...

  9. 西安邀请赛-E(树链剖分+线段树)

    题目链接:https://nanti.jisuanke.com/t/39272 题意:给一棵树,n个结点,树根为1,n-1条边,每个结点有一个权值.进行3种操作: 1 s t:把1和s之间的最短路径上 ...

随机推荐

  1. MAthJax入门教程(五分钟上手)

    最近在研究,在页面中显示一些数学公式.搞得我很头疼. 据说MathJax会统一这已领域.所以去学了学.网上教程特别多.繁杂. 说的清楚的特别少. 我是这么跑通的,: 1.在官网下载代码地址为:http ...

  2. Asp.Net Core 使用Docker进行容器化部署(二)使用Nginx进行反向代理

    上一篇介绍了Asp.Net 程序在Docker中的部署,这篇介绍使用Nginx对Docker的实例进行反向代理 一.修改Nginx配置文件 使用winscp链接Liunx服务器,在/ect/nginx ...

  3. Python进阶-函数默认参数

    Python进阶-函数默认参数 写在前面 如非特别说明,下文均基于Python3 一.默认参数 python为了简化函数的调用,提供了默认参数机制: def pow(x, n = 2): r = 1 ...

  4. 原lnmp环境服务器升级为mysql+nginx+php单个docker容器构建的lnmp环境

    时间:2018年2月 一.项目背景 我单位现web服务架构为lnmp环境,服务器软件.硬件升级部署难:同时开源软件日新月异,考虑到技术升级,领导决定服务器架构整体升级为容器架构,维护性.移植性强. 二 ...

  5. R语言学习笔记(十七):data.table包中melt与dcast函数的使用

    melt函数可以将宽数据转化为长数据 dcast函数可以将长数据转化为宽数据 > DT = fread("melt_default.csv") > DT family_ ...

  6. dijkstra算法学习

    dijkstra算法学习 一.最短路径 单源最短路径:计算源点到其他各顶点的最短路径的长度 全局最短路径:图中任意两点的最短路径 Dijkstra.Bellman-Ford.SPFA求单源最短路径 F ...

  7. Android开发——Google关于Application Not Responding的建议

    秒内没有执行完毕. 2.       避免ANR的一些建议 Android applications normally run entirely on asingle (i.e. main) thre ...

  8. LeetCode:24. Swap Nodes in Pairs(Medium)

    1. 原题链接 https://leetcode.com/problems/swap-nodes-in-pairs/description/ 2. 题目要求 给定一个链表,交换相邻的两个结点.已经交换 ...

  9. 学习SQLite基本语句

    SQLite 是一个开源的嵌入式关系数据库,实现自包容.零配置.支持事务的SQL数据库引擎. 其特点是高度便携.使用方便.结构紧凑.高效.可靠. 与其他数据库管理系统不同,SQLite 的安装和运行非 ...

  10. 如何删除TFS项目

    TFS是先建集合,再在集合下面建项目.删除的时候,需要先删除项目,再删除集合,然后重新建.具体步骤如下: 1.删除项目        删除项目必须通过命令来进行删除,调用TFSDeleteProjec ...