[luogu4556][Vani有约会]
吐槽
这道题调了7个小时也是够了。最后只好比着题解做了一遍2333
思路
首先考虑n=2000的情况。因为这是在一条路径上,所以可以考虑差分。用a[i][j]表示第i个点中j这种粮食出现的次数。加入要在从x到y的路径上加入c这种粮食。将这条路径分为两部分进行差分。从x到lca,也就是将a[x][c]++,a[fa[lca]]--。从y到son[lca]。就是将a[y][c]++,a[lca]--。(详细原因见树上差分)最后dfs一遍,并且在回溯的时候合并一下就行了。
那么对于n=100000的数据,只要用线段树合并优化一下就行了。也就是将a数组改为n棵动态开点线段树。合并的时候用线段树合并的板子合并一下就行了。
代码
/*
* @Author: wxyww
* @Date: 2018-12-10 14:37:11
* @Last Modified time: 2018-12-10 21:15:06
*/
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
#define Ls TR[cur].ls
#define Rs TR[cur].rs
ll read() {
ll x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
const int N = 100000 + 100,logN = 20;
struct node {
int ls,rs,ans,sum;
}TR[N * 50];
int n,m,dep[N],lca[N][logN + 30],root[N];
vector<int>e[N];
int num;
void get_lca(int u,int father) {
for(int i = 1;i < logN;++i) lca[u][i] = lca[lca[u][i - 1]][i - 1];
int k = e[u].size();
for(int i = 0;i < k;++i) {
int v = e[u][i];
if(v == father) continue;
lca[v][0] = u;
dep[v] = dep[u] + 1;
get_lca(v,u);
}
}
int LCA(int x,int y) {
if(dep[x] < dep[y]) swap(x,y);
for(int i = logN - 1;i >= 0;--i)
if(dep[lca[x][i]] >= dep[y]) x = lca[x][i];
if(x == y) return y;
for(int i = logN - 1;i >= 0;--i) {
if(lca[x][i] != lca[y][i]) {
x = lca[x][i];y = lca[y][i];
}
}
return lca[x][0];
}
void up(int cur) {
if(TR[Ls].sum >= TR[Rs].sum) {
TR[cur].sum = TR[Ls].sum;
TR[cur].ans = TR[Ls].ans;
}
else {
TR[cur].sum = TR[Rs].sum;
TR[cur].ans = TR[Rs].ans;
}
}
void update(int &cur,int l,int r,int pos,int c) {
if(!cur) cur = ++num;
if(l == r) {
TR[cur].sum += c;
TR[cur].ans = l;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(Ls,l,mid,pos,c);
else update(Rs,mid + 1,r,pos,c);
up(cur);
}
int merge(int cur,int a,int l,int r) {
if(!cur) return a;
if(!a) return cur;
if(l == r) {
TR[cur].sum += TR[a].sum;
TR[cur].ans = l;
return cur;
}
int mid = (l + r) >> 1;
Ls = merge(Ls,TR[a].ls,l,mid);
Rs = merge(Rs,TR[a].rs,mid + 1,r);
up(cur);
return cur;
}
void dfs(int u,int father) {
int k = e[u].size();
for(int i = 0;i < k;++i) {
int v = e[u][i];
if(v == father) continue;
dfs(v,u);
merge(root[u],root[v],1,N - 100);
}
}
int main() {
int n = read(),m = read();
for(int i = 1;i < n;++i) {
int x = read(),y = read();
e[x].push_back(y);
e[y].push_back(x);
}
dep[1] = 1;
for(int i = 1;i <= n;++i) root[i] = ++num;
get_lca(1,0);
while(m--) {
int x = read(),y = read(),c = read();
int K = LCA(x,y);
update(root[x],1,N - 100,c,1);
update(root[y],1,N - 100,c,1);
update(root[K],1,N - 100,c,-1);
if(lca[K][0]) update(root[lca[K][0]],1,N - 100,c,-1);
}
dfs(1,0);
for(int i = 1;i <= n;++i) {
if(TR[root[i]].sum == 0) puts("0");
else
printf("%d\n",TR[root[i]].ans);
}
return 0;
}
[luogu4556][Vani有约会]的更多相关文章
- 「Luogu4556」Vani有约会-雨天的尾巴
「Luogu4556」Vani有约会-雨天的尾巴 传送门 很显然可以考虑树上差分+桶,每次更新一条链就是把这条链上的点在桶对应位置打上 \(1\) 的标记, 最后对每个点取桶中非零值的位置作为答案即可 ...
- [Vani有约会]雨天的尾巴 线段树合并
[Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...
- 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告
P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...
- P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)
P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...
- P4556 [Vani有约会]雨天的尾巴 (线段树合并)
P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋 ...
- [题解] P4556 [Vani有约会]雨天的尾巴
[题解] P4556 [Vani有约会]雨天的尾巴 ·题目大意 给定一棵树,有m次修改操作,每次修改 \(( x\) \(y\) \(z )\) 表示 \((x,y)\) 之间的路径上数值 \(z\) ...
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- [Vani有约会]雨天的尾巴
嘟嘟嘟 看到链上操作,自然想到树剖. 先考虑序列上的问题:那么区间修改可以用差分.所以我们把操作拆成\(L\)和\(R + 1\)两个点,然后离线.排序后扫一遍,用线段树维护数量最多的颜色是哪一个. ...
- [Vani有约会]雨天的尾巴(树上差分+线段树合并)
首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所有的救济粮 ...
随机推荐
- varnish4 配置文件整理
vim default.vcl # 使用varnish版本4的格式. vcl 4.0; # 加载后端轮询模块 import directors; #######################健康检查 ...
- python数据结构与算法第十一天【希尔排序】
1.希尔排序的原理 2.代码实现 def shell_sort(alist): n = len(alist) # 初始步长 gap = n / 2 while gap > 0: # 按步长进行插 ...
- django celery redis 定时任务
0.目的 在开发项目中,经常有一些操作时间比较长(生产环境中超过了nginx的timeout时间),或者是间隔一段时间就要执行的任务. 在这种情况下,使用celery就是一个很好的选择. cele ...
- crontab 从nano 转换为 vim
crontab默认编辑器为nano,不方便使用. 修改crontab默认编辑器为vi或者其他的编辑器. export EDITOR="/usr/bin/vim" ; cront ...
- phonegap-plugin-contentsync
一.API 1.ContentSync.sync(options) options.src : 字符串类型 (必选项)远程托管内容的URL.更新一个生产环境下的APP,常使用HTTPS option ...
- Lodop提示安装或升级的注意事项
LODOP的LodopFuncs.js文件里,自动判断浏览器类型提示下载哪个,根据版本号比较判断提示升级.此文章是以前写的,图示可能过旧,新版提示不同,但是LodopFuncs.js里各个方面变动不大 ...
- Real-time chart using ASP.NET Core and WebSocket
Solution in glance The following diagram illustrates our solution where IoT device reports readings ...
- 实验吧 WEB 猫抓老鼠
人生的第一道CTF题目哇,鸡冻 其实只是学了一下HTTP抓包得到的都是什么,就开始上手胡搞了 题目名字叫猫抓老鼠,还疯狂暗示catch!catch!catch!catch!,就想到要用抓包其实我是因为 ...
- mvc HTML转Excel身份证后三位变成0
@{ var style = "vnd.ms-excel.numberformat:@"; } //HTML <td style=@style><span> ...
- VSCode里面HTML添加CSS时没有提示
看到知乎上的回答,vscode修改设置的: "editor.parameterHints": true, "editor.quickSuggestions": ...