【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6039

【题目大意】

  给出一些齿轮,有些齿轮是边相连,也就是拥有相同的线速度,
  有的齿轮是轴相连,也就是拥有相同的角速度,现在给某个齿轮一个速度,
  求这些齿轮中的最大速度,同时还有修改操作,可以更改某个齿轮的半径大小

【题解】

  对于共边的齿轮,有logwy=logwx+logrx-logry,
  对于同轴的齿轮,他们的速度是相同的,
  我们将具有关系的齿轮连在一起,对于每个连通块选取一个参考齿轮,
  别的齿轮则维护与其的相对关系,
  当有修改操作的时候,如下图:

  如果我们将齿轮p的半径变大,我们发现其同轴的齿轮相对参考齿轮都会变慢,
  同时其轴的子树部分受其影响也会变慢,
  但是我们发现只有蓝色的齿轮B和C会变慢,
  红色的齿轮这一部分由于拥有和修改的齿轮相同的线速度而保持了速度不变,
  所以,我们每次更新两段dfs序,将同轴与其管辖部分先处理,
  然后将其线速度相同的管辖部分用相反数再处理一遍,
  对于查询操作,我们可以求出被施加速度的齿轮和连通块中相对速度最大的齿轮的差
  加上施加速度就是答案。

【代码】

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int INF=~0U>>1;
const double ln2=log(2.);
const int N=100010,M=N<<2;
int n,m,k,d[N],f[N];
struct Edge{int v,w,r;};
vector<int> v[N];
vector<Edge> E[N];
bool mark[N];
int rad[N],l[N],r[N],L[N],R[N],rt[N];
int log2(int x){int d;while(x>>=1)d++;return d;}
namespace Segment_Tree{
int tot;
struct node{int l,r,a,b,tag,val;}T[M];
void build(int,int);
void Initialize(int n){
tot=0;
build(1,n);
}
void addtag(int x,int tag){
T[x].tag+=tag;
T[x].val+=tag;
}
void pb(int x){
if(T[x].l){addtag(T[x].l,T[x].tag);addtag(T[x].r,T[x].tag);}
T[x].tag=0;
}
void up(int x){T[x].val=max(T[T[x].l].val,T[T[x].r].val);}
void build(int l,int r){
int x=++tot;
T[x].a=l;T[x].b=r;T[x].tag=T[x].l=T[x].r=T[x].val=0;
if(l==r){T[x].val=d[l];return;}
int mid=(l+r)>>1;
T[x].l=tot+1;build(l,mid);
T[x].r=tot+1;build(mid+1,r);
up(x);
}
void change(int x,int a,int b,int p){
if(T[x].a>=a&&T[x].b<=b){addtag(x,p);return;}
if(T[x].tag)pb(x);
int mid=(T[x].a+T[x].b)>>1;
if(mid>=a&&T[x].l)change(T[x].l,a,b,p);
if(mid<b&&T[x].r)change(T[x].r,a,b,p);
up(x);
}
int query(int x,int a,int b){
if(T[x].a>=a&&T[x].b<=b)return T[x].val;
if(T[x].tag)pb(x);
int mid=(T[x].a+T[x].b)>>1; int res=-INF;
if(mid>=a&&T[x].l)res=max(res,query(T[x].l,a,b));
if(mid<b&&T[x].r)res=max(res,query(T[x].r,a,b));
return res;
}
}
int cnt;
void dfs(int Rt,int fx,int x,int _d){
rt[x]=Rt;
d[l[x]=++cnt]=_d;
for(int i=0;i<E[x].size();i++){
Edge e=E[x][i];
if(e.v==fx){mark[e.w]=1;}
else{
L[e.w]=min(L[e.w],cnt+1);
dfs(Rt,x,e.v,_d+e.r);
R[e.w]=max(R[e.w],cnt);
}
}r[x]=cnt;
}
void print(int k){printf("%.3f\n",k*ln2);}
int sf(int x){return f[x]==x?x:f[x]=sf(f[x]);}
int Cas=1,op,x,y;
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
for(int i=1;i<=n;i++){
f[i]=i;
L[i]=INF,R[i]=rt[i]=0;
mark[i]=0;
v[i].clear(); E[i].clear();
scanf("%d",&rad[i]);
rad[i]=log2(rad[i]);
}
while(m--){
scanf("%d%d%d",&op,&x,&y);
if(op-1){f[sf(x)]=sf(y);}
else{v[x].push_back(y);v[y].push_back(x);}
}
for(int i=1;i<=n;i++){
for(int k=0;k<v[i].size();k++){
int j=v[i][k];
E[sf(i)].push_back((Edge){sf(j),i,rad[i]-rad[j]});
}
}cnt=0;
for(int i=1;i<=n;i++){if(sf(i)==i&&!rt[sf(i)])dfs(f[i],0,f[i],0);}
using namespace Segment_Tree;
Initialize(cnt);
printf("Case #%d:\n",Cas++);
while(k--){
scanf("%d%d%d",&op,&x,&y);
y=log2(y);
if(op-1){
x=sf(x);
print(y-query(1,l[x],l[x])+query(1,l[rt[x]],r[rt[x]]));
}else{
int fx=sf(x),d=y-rad[x];
if(mark[x])change(1,l[fx],r[fx],-d);
if(L[x]<=R[x])change(1,L[x],R[x],d);
rad[x]=y;
}
}
}return 0;
}

HDU 6039 Gear Up(线段树+并查集)的更多相关文章

  1. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  2. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  3. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  4. HDU 5809 Ants(KD树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5809 [题目大意] 给出一些蚂蚁和他们的巢穴,一开始他们会在自己的巢穴(以二维坐标形式给出),之后 ...

  5. 【XSY2707】snow 线段树 并查集

    题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...

  6. bzoj 2054: 疯狂的馒头(线段树||并查集)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...

  7. 【CF687D】Dividing Kingdom II 线段树+并查集

    [CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...

  8. 【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集

    [BZOJ1453][Wc]Dface双面棋盘 Description Input Output Sample Input Sample Output HINT 题解:话说看到题的第一反应其实是LCT ...

  9. codeforces 811E Vladik and Entertaining Flags(线段树+并查集)

    codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...

  10. 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]

    Vladik and Entertaining Flags Time Limit: 20 Sec  Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...

随机推荐

  1. 【洛谷 P4735】 最大异或和 (可持久化Trie)

    题目链接 维护整个数列的异或前缀和和\(s\),然后每次就是要求\(s[N]\text{^}x\text{^}s[k],l-1<=k<=r-1\)的最大值 如果没有\(l\)的限制,那么直 ...

  2. 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)

    题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...

  3. sumblime快捷键

    原文地址:https://blog.csdn.net/shutfuckingup/article/details/23846603 Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的 ...

  4. Codeforces Round #478 (Div. 2)

    题目链接:http://codeforces.com/contest/975 A. Aramic script time limit per test:1 second memory limit pe ...

  5. httpd -v command not found

    使用 find / -name "apachectl"查找文件目录下执行 ./apachectl -v

  6. C++转换构造函数和隐式转换函数 ~ 转载

    原文地址: C++转换构造函数和隐式转换函数 用转换构造函数可以将一个指定类型的数据转换为类的对象.但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成doubl ...

  7. AGC025简要题解

    AGC025简要题解 B RGB Coloring 一道简单题,枚举即可. C Interval Game 考虑可以进行的操作只有两种,即左拉和右拉,连续进行两次相同的操作是没有用的. 左拉时肯定会选 ...

  8. [转载]循规蹈矩:快速读懂SQL执行计划的套路与工具

    作者介绍 梁敬彬,福富研究院副理事长.公司唯一四星级内训师,国内一线知名数据库专家,在数据库优化和培训领域有着丰富的经验.多次应邀担任国内外数据库大会的演讲嘉宾,在业界有着广泛的影响力.著有多本畅销书 ...

  9. XMLDocument 方法中实现post发送消息

    XMLDocument 方法中实现post发送消息

  10. [hadoop][会装]hadoop ha模式安装

    1.简介 2.X版本后namenode支持了HA特性,使得整个文件系统的可用性更加增强. 2.安装前提 zookeeper集群,zookeeper的安装参考[hadoop][会装]zookeeper安 ...