题意:给出一个有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的更多相关文章

  1. 题解:CF593D Happy Tree Party

    题解:CF593D Happy Tree Party Description Bogdan has a birthday today and mom gave him a tree consistin ...

  2. CF593D Happy Tree Party(不用树剖)

    题面 题解 我们发现,对于除法有效的xi最小为2,yi最多除log次就会变成0,所以我们可以每次找路径上下一个>=2的xi,暴力除,当发现y=0时就停止 于是我们维护每个点向上走一直走到根最近的 ...

随机推荐

  1. JS文件加载:比较async和DOM Script

    async与script动态加载都能使文件异步加载,本文叙述它们对页面渲染和load加载的影响方面. 目前我用demo.js作为执行文件操作.代码: var now = function() { re ...

  2. 学习C++.Primer.Plus 11 使用类

    1.操作符重载 重载操作符的几个限制: a)         重载的至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符. b)         不能违反操作符原有来的句法规则. c)  ...

  3. 快速部署tomcat项目的Shell脚本

    为了做集群测试,在每台机器上装了3个tomcat,每次发布项目的时候都要反复敲一些命令,重启tomcat之前先检查tomcat进程有没有停掉,没有还要手动kill该进程. 发布次数多了,操作就比较繁琐 ...

  4. 51Nod-1091 线段的重叠

    51Nod 1091:  http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1091   1091 线段的重叠 基准时间限制: ...

  5. 五种开源协议(GPL,LGPL,BSD,MIT,Apache)

    什么是许可协议? 什么是许可,当你为你的产品签发许可,你是在出让自己的权利,不过,你仍然拥有版权和专利(如果申请了的话),许可的目的是,向使用你产品的人提供 一定的权限. 不管产品是免费向公众分发,还 ...

  6. bzoj4462: [Jsoi2013]编程作业

    KMP还是有点用处的嘛qwq 对于小写字母,修改其为前一个这个小写字母和它的距离 然后跑KMP就行了 跑得飞快 #include <iostream> #include <cstdi ...

  7. Ruby升级的最新方法

    今天安装cocoapods时候出现了下面的提示Error installing pods:active support requires Ruby version >= 2.2.0这个需求的意思 ...

  8. js jquery 页面加载初始化方法

    js jquery 页面加载初始化方法 一.js页面加载初始化方法 // 1.在body里面写初始化方法. <body onload='init()'> </body> < ...

  9. 【Alpha版本】冲刺随笔汇总

    [Alpha版本]冲刺-Day1 [Alpha版本]冲刺-Day2 [Alpha版本]冲刺-Day3 [Alpha版本]冲刺-Day4 [Alpha版本]冲刺-Day5 [Alpha版本]冲刺-Day ...

  10. C#的winform控件命名规范

    注:这里用红字标记的部分表示有重复出现,括号内为替代表示方案 1.标准控件 序号 控件类型简写 控件类型 1 btn Button 2 chk CheckBox 3 ckl CheckedListBo ...