HDU 6039 Gear Up(线段树+并查集)
【题目链接】 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(线段树+并查集)的更多相关文章
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)
2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- HDU 5809 Ants(KD树+并查集)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5809 [题目大意] 给出一些蚂蚁和他们的巢穴,一开始他们会在自己的巢穴(以二维坐标形式给出),之后 ...
- 【XSY2707】snow 线段树 并查集
题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...
- bzoj 2054: 疯狂的馒头(线段树||并查集)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...
- 【CF687D】Dividing Kingdom II 线段树+并查集
[CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...
- 【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集
[BZOJ1453][Wc]Dface双面棋盘 Description Input Output Sample Input Sample Output HINT 题解:话说看到题的第一反应其实是LCT ...
- codeforces 811E Vladik and Entertaining Flags(线段树+并查集)
codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...
- 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]
Vladik and Entertaining Flags Time Limit: 20 Sec Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...
随机推荐
- 程序员你为什么这么累? - Controller规范
导读:程序员你为什么这么累? 接口定义:程序员你为什么这么累? - 接口定义 第一篇文章中,我贴了2段代码,第一个是原生态的,第2段是我指定了接口定义规范,使用AOP技术之后最终交付的代码,从15行到 ...
- Python 下调用C动态链接库 -- (转)
在linux开发的动态链接库需要被python调用,首先需要生成.so文件. 生成动态链接库的方法网上有很多,主要就是首先根据源文件编译生成.o,然后链接这些.o文件-shared生成.so.需要注意 ...
- linux之cron定时任务介绍
前言 linux系统有一个专门用来管理定时任务的进程cron,一般是设置成开机自启动的,通过添加任务可以让服务器定时执行某些任务. cron介绍 linux系统有一个专门用来管理定时任务的进程cron ...
- 写个dump_stack【转】
转自:http://blog.chinaunix.net/uid-27714502-id-3434761.html 简单实现dump_stack 0.首先确保你能写个内核模块:打印"hell ...
- 使用UpdatePanel时FileUpload失效的问题
出处:http://www.cnblogs.com/caicainiao/archive/2010/12/08/1900377.html 1.使用UpdatePanel后,FileUpload的Has ...
- 【bzoj4765】普通计算姬
一道奇奇怪怪的数据结构题? 把树线性化,然后分块维护吧. 为了加速,求和用树状数组维护每个块的值. #include<bits/stdc++.h> #define N 100010 #de ...
- 【模板】BZOJ 3685: 普通van Emde Boas树——Treap
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3685 据说神犇都是用zkw线段树水过的啊... 我蒟蒻只会写treap,加了fread之后8 ...
- 坐标转换——GCJ-02
WGS84(World Geodetic System 1984),是为GPS 全球定位系统 使用而建立的坐标系统GCJ-02,我国在WGS84的基础上加密得到BD-09,百度坐标在GCJ-02基础上 ...
- mycncart自定义主题
本文是自己通过其他主题,自学的,如果有什么问题,可以提出建议? 参考资料:opencart官网 www.opencart.com 或 mycncart的官网上的一些教程 www.mycncart.c ...
- django开发项目实例3--用session是实现简单的登陆、验证登陆和注销功能
如果你的网页不是纯阅读型的,那么你很有可能希望在用户打开某些界面的时候需要验证用户是否登陆的信息, 虽然django里面有自带的一些user的类,但我看不懂,并且自己实现也不是很难,下面和大家分享一下 ...