题目地址: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. 浅谈linux系统中pdf文件的默认打开方式

    atril.gimp和evince,三者均可以打开application/pdf格式文件.gimp为一款图像处理软件:atril为mate环境下常用的文档查看器:evince为gnome环境下常用的文 ...

  2. GUI小程序---理解GUI

    package com.gui; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent ...

  3. JAVAOOP I/O

    程序的主要任务就是操作数据,通过允许程序读取文件的内容或向文件写入数据,可以使程序应用更加广泛. I/O(input/output) 在不同操作系统之下,所占的字节数也不同,一般认为 8.1.1使用F ...

  4. 【c学习-9】

    /*内存练习*/ #include #include//引入内存分配库文件 int main(){ double* x; //定义整型指针和double指针 int* y; x=(double*)ma ...

  5. yii 自带RBAC

    common:中加 'authManager' => [ 'class' => 'yii\rbac\DbManager', 'itemTable' => 'auth_item', ' ...

  6. php导出excel长数字串显示为科学计数方法与最终解决方法

    1.设置单元格为文本 $objPHPExcel = new PHPExcel(); $objPHPExcel->setActiveSheetIndex(0); $objPHPExcel-> ...

  7. 2.5 进程控制之wait函数

    一.绪论 一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果 是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是 ...

  8. Leecode刷题之旅-C语言/python-100相同的树

    /* * @lc app=leetcode.cn id=100 lang=c * * [100] 相同的树 * * https://leetcode-cn.com/problems/same-tree ...

  9. POJ2553 汇点个数(强连通分量

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12070   Accepted: ...

  10. ffplay使用笔记

    ffplay播放yuv文件命令: ffplay -f rawvideo -video_size 1920x1080 a.yuv   ffplay播放mp4.h.264.hevc文件命令: ffplay ...