cf593d
题意:给出一个有n(n<=200000)的树形图,每条边有一个权值。有两种操作,1是将一个边的权值变小,
2是给定两点a,b和一个值y,用y(long long范围内)依次除以两点之间的路径上的所有边的权值,每次除法都是向下取整。
并输出这个值。
操作次数为m(m<=200000)。
分析:
这是一个较难的在线LCA问题。
首先,每个y最多经过63次>=2的除数的除法就会变为0。
建树并生成LCA。
每次处理第2种请求时,我们都是先求两点的LCA,再分别处理两点到其LCA的路径。
对于从低到高走路径的过程中,连续的权值为1的边,我们用一种类似于并查集的方式将他们缩成一条边。
例如:a是b的父亲,边权值为1。那么我们领link[b]=a。否则我们令link[b]=b。
这样如果出现连续的权值为1的边,我们不断追溯其link值直到与自身相等即可。记得使用并查集的路径压缩优化。
那么我们处理单个路径时最多需要处理的边数约为63×2(权值>=2的和=1的边交替出现的情况)。
所以总复杂度为O(mlogy)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std; #define d(x)
const int MAX_NODE_NUM = (int)(2e5) + ;
const int M = ; int n, m;
vector<pair<int, long long> > edge[MAX_NODE_NUM];
bool vis[MAX_NODE_NUM];
int father[MAX_NODE_NUM][M];
int depth[MAX_NODE_NUM];
long long value[MAX_NODE_NUM];
pair<int, int> p_edge[MAX_NODE_NUM];
int link[MAX_NODE_NUM]; void bfs(int root)
{
queue<int> q;
q.push(root);
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = true;
for (int i = ; i < (int)edge[u].size(); i++)
{
int v = edge[u][i].first;
if (vis[v])
{
continue;
}
father[v][] = u;
depth[v] = depth[u] + ;
value[v] = edge[u][i].second;
link[v] = v;
if (u != && value[v] == )
link[v] = u;
q.push(v);
}
}
} //index start from 1.
void init_LCA(int root)
{
fill_n(vis, n + , );
memset(father, , sizeof(father));
bfs(root);
bool did;
for (int i = ; i < M; i++)
{
did = false;
for (int j = ; j <= n; j++)
{
int k = father[j][i - ];
if (k <= )
{
continue;
}
father[j][i] = father[k][i - ];
did = true;
}
if (!did)
{
break;
}
}
} //O(log(n))
int LCA(int x, int y)
{
if (depth[x] > depth[y])
{
swap(x, y);
}
int diff = depth[y] - depth[x];
for (int i = ; i < M && diff; i++)
{
if (diff & )
{
y = father[y][i];
}
diff >>= ;
}
if (x == y)
{
return x;
}
int exp = ;
while (x != y)
{
if (!exp || father[x][exp] != father[y][exp])
{
x = father[x][exp];
y = father[y][exp];
exp++;
}else
{
exp--;
}
}
return x;
} long long next_ll()
{
long long a;
scanf("%lld", &a);
return a;
} void input()
{
scanf("%d%d", &n, &m);
for (int i = ; i < n - ; i++)
{
int a, b;
long long c; scanf("%d%d", &a, &b);
c = next_ll();
edge[a].push_back(make_pair(b, c));
edge[b].push_back(make_pair(a, c));
p_edge[i] = make_pair(a, b);
}
} int get_link(int a)
{
if (a == link[a])
return a;
return link[a] = get_link(link[a]);
} void make(int a, int lca, long long &w)
{
while (w > && depth[a] > depth[lca])
{
w /= value[a];
a = father[a][];
a = get_link(a);
}
} void work(int a, int b, long long w)
{
int lca = LCA(a, b);
make(a, lca, w);
make(b, lca, w);
printf("%lld\n", w);
} void work(int p, long long w)
{
p--;
int u = p_edge[p].first;
int v = p_edge[p].second;
if (depth[u] > depth[v])
{
swap(u, v);
}
value[v]= w;
if (w == )
{
link[v] = link[u];
}
} int main()
{
input();
init_LCA();
for (int i = ; i < m; i++)
{
int command;
int a, b;
long long c;
scanf("%d", &command);
if (command == )
{
scanf("%d%d", &a, &b);
c = next_ll();
work(a, b, c);
}else
{
scanf("%d", &a);
c = next_ll();
work(a, c);
}
}
return ;
}
cf593d的更多相关文章
- 题解:CF593D Happy Tree Party
题解:CF593D Happy Tree Party Description Bogdan has a birthday today and mom gave him a tree consistin ...
- CF593D Happy Tree Party(不用树剖)
题面 题解 我们发现,对于除法有效的xi最小为2,yi最多除log次就会变成0,所以我们可以每次找路径上下一个>=2的xi,暴力除,当发现y=0时就停止 于是我们维护每个点向上走一直走到根最近的 ...
随机推荐
- rpc框架之HA/负载均衡构架设计
thrift.avro.grpc之类的rpc框架默认都没有提供负载均衡的实现,生产环境中如果server只有一台,显然不靠谱,于是有了下面的设计,这其实是前一阵跟北京一个朋友在qq群里交流的结果,分享 ...
- Libsvm Matlab 快速安装教程 (适用于Win7+, 64bit, and Matlab2016a+)
近日在开始学习Machine Learning SVM 相关算法,将Matlab平台安装SVM的步骤记录如下,亲测可用: 开发环境: Windows 8 64 bit, Matlab 2016a, S ...
- JAVA格物致知基础篇:你所不知道的返回码
上篇我们主要讲解利用Jersey组件如何来写一个能保证基本运行的Rest Service, 之所以说能够基本运行是因为接口暴露及其简易,一旦遇到其他的情况了,就无法正确的处理我们的请求.同时,这个接口 ...
- async/await Task Timeout
async/await Task Timeout 在日常的电脑使用过程中,估计最难以忍受的就是软件界面"卡住""无响应",在我有限的开发生涯中一直都是在挑战 它 ...
- iOS——学习网址收集+如何提高iOS开发技能
1 一个比系统自带的终端好用的软件:http://www.iterm2.com 2 学习和遇到技术问题可以去的网站: CocoaChina http://developer.cocoachi ...
- Eclipse JEE 安装JBPM 4.4 GPD
回顾往昔,发现自己好久没写博客了,想想以前自己是多么热衷于写博客分享,虽然分享的都是比较基础的东西,但每每看到访问量不断增加的时候内心还是爽爽的. 时间过的真的很快,离开学校和团队已经一个月了.来到了 ...
- .Net配置中心-简介
系统简介 最近做了一个.Net配置中心,本质就是将原本放在各个站点下AppSettings中的配置统一管理,可以实现一次更改,自动更新,这里提供了两个版本, 一个是心跳版,一个是zookeeper版. ...
- 拿什么拯救你,我的代码--c#编码规范实战篇
此文为译文,原文地址请点击. 本文通过重构一个垃圾代码,阐述了如何写出优秀的代码.开发人员及代码审核人员需按照此规范开发和审核代码.此规范以C#为例,JAVA的童鞋一并参考,C++的童鞋自行脑补吧. ...
- sys
sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sys.maxi ...
- VS2015链接错误一则
以前天真的以为C是C++的子集,.c文件直接.cpp命名没什么影响: 后缀一改 链接器工具错误 LNK2019