建模简析:

/*
HDU 6039 - Gear Up [ 建模,线段树,图论 ] | 2017 Multi-University Training Contest 1
题意:
给你n个齿轮,有些齿轮是同轴的(角速度相同),有些是同边的(线速度相同),任意两个齿轮两种关系中至多只有一种,且任意两个齿轮之间只有一条路径
给出所有齿轮的半径和 m组两两之间的关系
两种操作:1. 把改变某个齿轮的半径; 2. 赋予某个齿轮一个角速度,问所有齿轮中最大的角速度是多少
分析:
相邻齿轮连边建图,原图是森林,按单棵树考虑。
由于同轴的齿轮在角速度上相同,故可缩点成齿轮组,新图上各组齿轮同边,且任意两个齿轮组只有一对齿轮同边
单棵树上的齿轮在角速度上有着倍数关系,故可以以某一个齿轮为参照,维护别的齿轮和它在角速度上的倍数
可以想象,以根节点为参照,齿轮组 u 对于根节点的角速度的倍数与其直接相邻的齿轮 f 的关系 Ku = Kf * Rf / Ru
当某个齿轮半径改变后,相当于区间修改子树的倍数,查询则是查询该齿轮所在树的最大值
大体看得出线段树模型,根据dfs序维护,但是乘法不易维护,则将上表达式取对数:log2(Ku) = log2(Kf) + log2(Rf) - log2(Ru)
维护对数则只需维护加减法,由于题中半径均为2的幂次,故对数取以二为底 查询操作容易写,修改操作需分类讨论
1.该齿轮是直接与上一个齿轮组同边的齿轮
该齿轮变大,同轴所有齿轮角速度变慢,与该齿轮直接同边的子树上的齿轮组不受影响,反之亦然
2.该齿轮不是直接与上一个齿轮组同边的齿轮
该齿轮变大,同轴所有齿轮角速度不受影响,与该齿轮直接同边的子树上的齿轮组变快,反之亦然 具体操作时,维护两个dfs序,一个是同轴齿轮组的整棵子树的dfs序,另一个是与该齿轮直接同边的子树dfs序
维护后一个dfs序时,可对于每一个节点,把这个节点所有连接的点排序,使得和该点同边的点在对应 vector 中的前缀里(就不用缩点了) 编码时长:8小时(-INF)
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
const int INF = 0x3f3f3f3f;
double ln2 = log(2.);
struct Edge{
int v, type;
};
bool cmp(Edge a, Edge b) {
return a.type > b.type;
}
vector<Edge> edge[N];
int rad[N], rate[N], f[N], rt[N];
int l[N], r[N], ll[N], rr[N], pos, p[N];
int n, m, q;
void init(){
for (int i = 0; i < N; i++) {
edge[i].clear();
ll[i] = INF;
l[i] = r[i] = rr[i] = 0;
f[i] = 0;
}
pos = 0;
}
void dfs(int u, int pre)
{
sort(edge[u].begin(), edge[u].end(), cmp);
rt[u] = rt[pre];
l[u] = ++pos;
p[pos] = u;
for (const auto& e : edge[u])
{
if (e.v == pre) continue;
if (e.type == 1) {
rate[e.v] = rad[u] - rad[e.v] + rate[u];
f[e.v] = e.v;
ll[u] = min(ll[u], pos+1);
dfs(e.v, u);
rr[u] = max(rr[u], pos);
} else {
rate[e.v] = rate[u];
f[e.v] = f[u];
dfs(e.v, u);
}
}
r[u] = pos;
}
int Max[N<<2], add[N<<2];
void Up(int x) {
Max[x] = max(Max[x<<1], Max[x<<1|1]);
}
void Down(int x) {
if (add[x]) {
Max[x<<1] += add[x];
Max[x<<1|1] += add[x];
add[x<<1] += add[x];
add[x<<1|1] += add[x];
add[x] = 0;
}
}
void Build(int l, int r, int x) {
add[x] = 0;
if (l == r) {
Max[x] = rate[p[l]]; return;
}
int mid = (l+r) >> 1;
Build(l, mid, x<<1); Build(mid+1, r, x<<1|1);
Up(x);
}
void Change(int L, int R, int num, int l, int r, int x) {
if (L <= l && r <= R) {
add[x] += num; Max[x] += num;
return;
}
Down(x);
int mid = (l + r) >> 1;
if (L <= mid) Change(L, R, num, l, mid, x<<1);
if (mid < R) Change(L, R, num, mid+1, r, x<<1|1);
Up(x);
}
int Query(int L, int R, int l, int r, int x) {
if (L <= l && r <= R) return Max[x];
Down(x);
int mid = (l+r) >> 1;
int res = -INF;
if (L <= mid) res = max(res, Query(L, R, l, mid, x<<1));
if (R > mid) res = max(res, Query(L, R, mid+1, r, x<<1|1));
return res;
}
int main()
{
int tt = 0, i, a, x, y;
while (~scanf("%d%d%d", &n, &m, &q))
{
init();
for (i = 1; i <= n; i++)
{
scanf("%d", &rad[i]);
rad[i] = log2(rad[i]);
}
for (i = 1; i <= m; i++)
{
scanf("%d%d%d", &a, &x, &y);
edge[x].push_back(Edge{y, a});
edge[y].push_back(Edge{x, a});
}
for (i = 1; i <= n; i++)
if (!f[i]) {
rt[i] = f[i] = i;
rate[i] = 0;
dfs(i, i);
}
Build(1, n, 1);
printf("Case #%d:\n", ++tt);
while (q--)
{
scanf("%d%d%d", &a, &x, &y);
if (a == 1)
{
y = log2(y);
if (f[x] == x && rt[x] != x) Change(l[x], r[x], rad[x]-y, 1, n, 1);
if (ll[x] <= rr[x]) Change(ll[x], rr[x], y-rad[x], 1, n, 1);
rad[x] = y;
}
else
{
int km = Query(l[rt[x]], r[rt[x]], 1, n, 1);
int k = Query(l[x], l[x], 1, n, 1);
double au = log2(y) + km - k;
printf("%.3f\n", au*ln2);
}
}
}
}

  

按标程的思路,不同的主要是缩点:

#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
const int INF = 0x3f3f3f3f;
double ln2 = log(2.);
int f[N];
int sf(int x) {
return x == f[x] ? x : f[x] = sf(f[x]);
}
struct Edge{ int v, w, dis; };
vector<int> edge[N];
vector<Edge> lnk[N];
int rad[N], rt[N], rate[N], up[N];
int l[N], r[N], ll[N], rr[N], pos;
int n, m, q;
void init()
{
for (int i = 0; i < N; i++)
{
f[i] = i;
edge[i].clear();
lnk[i].clear();
l[i] = r[i] = 0;
ll[i] = INF;
rt[i] = up[i]= rr[i] = 0;
}
pos = 0;
}
void dfs(int u, int pre, int root, int dis)
{
rt[u] = root;
l[u] = ++pos;
rate[l[u]] = dis;
for (const auto &e: lnk[u])
{
if (pre == e.v) {
up[e.w] = 1;
} else {
ll[e.w] = min(ll[e.w], pos+1);
dfs(e.v, u, root, dis+e.dis);
rr[e.w] = max(rr[e.w], pos);
}
}
r[u] = pos;
}
int Max[N<<2], add[N<<2];
void Up(int x) {
Max[x] = max(Max[x<<1], Max[x<<1|1]);
}
void Down(int x) {
if (add[x]) {
Max[x<<1] += add[x];
Max[x<<1|1] += add[x];
add[x<<1] += add[x];
add[x<<1|1] += add[x];
add[x] = 0;
}
}
void Build(int l, int r, int x) {
add[x] = 0;
if (l == r) {
Max[x] = rate[l]; return;
}
int mid = (l+r) >> 1;
Build(l, mid, x<<1); Build(mid+1, r, x<<1|1);
Up(x);
}
void Change(int L, int R, int num, int l, int r, int x) {
if (L <= l && r <= R) {
add[x] += num; Max[x] += num;
return;
}
Down(x);
int mid = (l + r) >> 1;
if (L <= mid) Change(L, R, num, l, mid, x<<1);
if (mid < R) Change(L, R, num, mid+1, r, x<<1|1);
Up(x);
}
int Query(int L, int R, int l, int r, int x) {
if (L == 0 || R == 0) return 0;
if (L <= l && r <= R) return Max[x];
Down(x);
int mid = (l+r) >> 1;
int res = -INF;
if (L <= mid) res = max(res, Query(L, R, l, mid, x<<1));
if (R > mid) res = max(res, Query(L, R, mid+1, r, x<<1|1));
return res;
}
int main()
{
int tt = 0, i, a, x, y;
while (~scanf("%d%d%d", &n, &m, &q))
{
init();
for (i = 1; i <= n; i++)
{
scanf("%d", &rad[i]);
rad[i] = log2(rad[i]);
}
for (i = 1; i <= m; i++)
{
scanf("%d%d%d", &a, &x, &y);
if (a == 1)
{
edge[x].push_back(y);
edge[y].push_back(x);
}
else f[sf(x)] = sf(y);
}
for (i = 1; i <= n; i++)
for (auto& x: edge[i])
lnk[sf(i)].push_back(Edge{sf(x), i, rad[i] - rad[x]});
for (i = 1; i <= n; i++)
if (sf(i) == i && !rt[i])
dfs(i, i, i, 0);
Build(1, pos, 1);
printf("Case #%d:\n", ++tt);
while (q--)
{
scanf("%d%d%d", &a, &x, &y);
if (a == 1)
{
y = log2(y);
int fx = sf(x);
if (up[x]) Change(l[fx], r[fx], rad[x]-y, 1, pos, 1);
if (ll[x] <= rr[x]) Change(ll[x], rr[x], y-rad[x], 1, pos, 1);
rad[x] = y;
} else {
x = sf(x);
int km = Query(l[rt[x]], r[rt[x]], 1, pos, 1);
int k = Query(l[x], l[x], 1, pos, 1);
double au = log2(y) + km - k;
printf("%.3f\n", au*ln2);
}
}
}
}

  

HDU 6039 - Gear Up | 2017 Multi-University Training Contest 1的更多相关文章

  1. hdu 6039 Gear Up

    题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6039 (2017 Multi-University Training Contest 1 1007) ...

  2. HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9

    /* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问 ...

  3. hdu 6301 Distinct Values (2018 Multi-University Training Contest 1 1004)

    Distinct Values Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  4. hdu 5288 OO’s Sequence(2015 Multi-University Training Contest 1)

    OO's Sequence                                                          Time Limit: 4000/2000 MS (Jav ...

  5. hdu 5416 CRB and Tree(2015 Multi-University Training Contest 10)

    CRB and Tree                                                             Time Limit: 8000/4000 MS (J ...

  6. HDU 6039 Gear Up(线段树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6039 [题目大意] 给出一些齿轮,有些齿轮是边相连,也就是拥有相同的线速度, 有的齿轮是轴相连,也 ...

  7. HDU 4944 FSF’s game(2014 Multi-University Training Contest 7)

    思路:  ans[n]=  ans[n-1] + { (n,1),(n,2).....(n,n)}  现在任务 是 计算  { (n,1),(n,2).....(n,n)}(k=n的任意因子) 很明显 ...

  8. HDU 4940 Destroy Transportation system(2014 Multi-University Training Contest 7)

    思路:无源汇有上下界可行流判定, 原来每条边转化成  下界为D  上界为 D+B   ,判断是否存在可行流即可. 为什么呢?  如果存在可行流  那么说明对于任意的 S 集合流出的肯定等于 流入的, ...

  9. HDU 4627 The Unsolvable Problem 2013 Multi-University Training Contest 3

    给你一个数 n ( 2 <= n <= 109 ),现在需要你找到一对数a, b (a + b = n),并且使得LCM(a, b)尽可能的大,然后输出最大的 LCM(a, b). (为什 ...

随机推荐

  1. 图解django的生命周期

    其实django的生命周期的大体框架就是这样,剩下的细致的,自己再补充! 图片实在是有点抽象! 谅解!! koala-----给你更多技术小干货

  2. 2 - sat 模板(自用)

    2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一  POJ 3207 Ikki's Story IV ...

  3. 怎样使用构造函数: Vue()?

    1. 新建一个 .html 文件 => 引入一个在线的 vue 库 => 写一个带 id 的 html 标签 => 写一个 script 标签, 这里的 vApp 是 Vue() 这 ...

  4. lua与c的交互(函数专用)

    Lua与C的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1.  读写L ...

  5. 【科创人·独家】连续创业者高春辉的这六年:高强度投入打造全球领先的IP数据库

    您能看到:高春辉的创业观,IPIP.NET半程复盘及未来规划,连续创业的体验,小众产品趣事 您看不到:往年创业的回顾,技术干货,受制于篇幅忍痛割舍的精彩观点 文末彩蛋:<与雷军的分歧并非否定电商 ...

  6. 自定义springboot-starter

    参考: https://juejin.im/entry/5b447cbbe51d45199566f752 https://www.baeldung.com/spring-boot-custom-sta ...

  7. shell脚本视频学习2

    一.函数 1.函数格式 2.函数传入参数 3.手动输入函数中的参数 4.函数返回值 成功返回0,失败返回1 5.输入一个目录,判断目录是否存在,如果不存在则给出提示,如果存在则提示输入要创建的文件名, ...

  8. ceres for Android 太慢的解决方法

    跨平台编译了ceres,结果在android平台上运行的太慢,优化一次要0.3秒左右,时不时要一两秒.这太扯了.没辙了,在google上瞎搜索,看到 Jacobian evaluation is ve ...

  9. SmartBinding与kbmMW#3

    前言 在SmartBinding #2中,我介绍了新的自动绑定功能,支持在Form设计器中直接定义绑定.不仅如此,kbmMW SmartBind还有更多很酷的功能,即将发布的kbmMW中的SmartB ...

  10. C++ void*解惑

    最近遇到void *的问题无法解决,发现再也无法逃避了(以前都是采取悄悄绕过原则),于是我决定直面它. 在哪遇到了? 线程创建函数pthread_create()的最后一个参数void *arg,嗯? ...