题目地址: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. VMware虚拟化NSX-Manager命令行更改admin用户密码

    1.1    登录到NSX-Manager命令行界面,输入用户名和密码登录到用户模式 Log in to the vSphere Client and select an NSX virtual ap ...

  2. MAC系统如何显示隐藏文件解决方法

    苹果Mac OS 操作系统下,隐藏文件默认为隐藏状态,隐藏文件是否显示有多种方法可以设置. 方法一: 打开终端,输入命令行 1.显示Mac隐藏文件的命令: defaults write com.app ...

  3. Asp.Net Core 生成图形验证码

    前几天有朋友问我怎么生成图片验证码,话不多说直接上代码. 支持.NET CORE开源.助力.NET Core社区发展. using System; using System.IO; using Sys ...

  4. django开发傻瓜教程-3-celery异步处理

    Ref: https://www.jianshu.com/p/6f8576a37a3e https://blog.csdn.net/Demo_3/article/details/78119951 ht ...

  5. centos7上部署新版 jumpserver 跳板机服务

    CentOS 7 建议在一个纯净的 centos7上进行下面的安装部署 关闭 selinux 和防火墙 [root@jumpserver ~]# setenforce 0 [root@jumpserv ...

  6. Leecode刷题之旅-C语言/python-35.搜索插入位置

    /* * @lc app=leetcode.cn id=35 lang=c * * [35] 搜索插入位置 * * https://leetcode-cn.com/problems/search-in ...

  7. C++ 指针初始化要注意的地方

    1. 声明多个指针的时候: int* P1,P2; 如上所示,声明的是创建一个指针P1和一个int型的变量P2.而不是声明的两个指针. 对每个指针变量名,都需要使用一个*. 在C++中,int* 是一 ...

  8. [Cracking the Coding Interview] 4.2 Minimal Tree 最小树

    Given a sorted(increasing order) array with unique integer elements, write an algorithm to create a ...

  9. python 字符串输入、输出函数print input raw_input

    一.输出print print输出是以不带引号的输出.(用户所见的输出) 二.input()  和  raw_input()输入函数 raw_input()会把输入数据转换成字符串形式: ------ ...

  10. springboot升级到2.x需要改动的地方

    由于需要跟进技术发展的脚步,对原有项目springboot进行2.0升级,但升级并不是说改一下版本就完事了,springboot2.0变动比较多,详细变化可以百度一下,下面针对升级springboot ...