【题目链接】 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. python学习笔记(五)数值类型和类型转换

    Python中的数值类型有: 整型,如2,520 浮点型,如3.14159,1.5e10 布尔类型 True和False e记法: e记法即对应数学中的科学记数法 >>> 1.5e1 ...

  2. webpack4.x 入门一篇足矣

    前言: webpack4出了以后,一些插件变化很大,和之前的版本使用方式不一样,新手入坑,本篇将介绍如何从一开始配置webpack4的开发版本,对css,js进行编译打包合并生成md5,CSS中的图片 ...

  3. HDU 1465 不容易系列之一 (错排公式+容斥)

    题目链接 Problem Description 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了! 做好"一件"事情尚且不易,若想永远成功而总从不失败,那更是难上 ...

  4. python基础===tkinter学习链接

    http://effbot.org/tkinterbook/tkinter-classes.htm

  5. Meld:文件及目录对比工具

    Meld:文件及目录对比工具 http://wowubuntu.com/meld.html http://meld.sourceforge.net/

  6. 微信小程序宽高适配

    小程序的宽任何机型都是750rpx,但是画布canvas的默认单位是px,可能会出现需要怪异的样式,我们可以用到 wx.getSystemInfoSync().windowWidth和 wx.getS ...

  7. MySQL乐观锁

    MySQL悲观锁是依靠数据库的锁机制来实现,以实现最大程度上的独占性.但由于现代的web系统一般都是高并发的,所以悲观锁在这样的情况下的适用性不高,所以我们有了和悲观锁相对应的乐观锁. 乐观锁,是说假 ...

  8. IE6下面的hover不兼容

    第一种解决方法: ie6中hover只是对a标签有作用 必须有href=“”,否则都不管用,如果不能写a标签,还想让ie6下有滑过效果,那只能写javascript或者jquery. 例如:ie6是不 ...

  9. HDU-5351

    MZL's Border Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  10. Flask 的系统学习

    详细看地址: http://www.cnblogs.com/wupeiqi/articles/7552008.html 一. 说明 Flask是一个基于Python开发并且依赖jinja2模板和Wer ...