HDU 6039 Gear Up(2017 Multi-University Training Contest 1)
来源:互联网 发布:项目计划表软件 编辑:程序博客网 时间:2024/06/06 00:00
题目链接:Here
题意:给你一些齿轮以及齿轮之间的关系,然后每次有两种操作:1.把第x个齿轮的半径更改为y;2.给第x个齿轮一个大小为y的角速度,问所有齿轮中最大的角速度的自然对数是多少。
解法:根据齿轮之间的连接关系(共角速度或者共线速度)建图,我们就得到了一片森林。每一棵树任取一个点作为参照点,然后对于操作对象所在的树单独考虑。先讨论操作1,如果被修改的节点的父节点和该节点是共角速度的,那么这个修改操作只会影响这个所有与这个节点共线速度的节点。如果该节点与父节点共线速度,那么操作会影响该节点以及所有与该节点共角速度的点。对于操作2,我们只需要减去这个点相对于参照点的值,然后再加上所在树的最大权值即可。
这里有两个trick:
1.由于每一个齿轮的半径一定是2的幂次,所以可以对半径直接取log2,那么我们每一次操作都变成了整数之间的运算,结果乘上log(2.0)就行,又好写又快~
2.对于每一个节点,把这个节点所有连接的点排序,使得和该点共角速度的点在对应vector中的前缀里,这样我们做修改操作的时候就可以分成两个区间讨论了。
#include <stdio.h>#include <iostream>#include <vector>#include <algorithm>#include <cstring>using namespace std;const int N = 100005;const double EPS = 1e-8;struct Node{ int l,r,v,tag;};vector<vector<Node> >root;//记录森林中的每一棵线段树的根节点int n,m,q,cnt,st,t,siz,bel[N],id[N],sz[N],rsz[N],f[N],r[N],bs[N];//数组分别代表编号为i的节点:属于第bel[i]棵线段树;在dfs序中的编号;子树大小;与该节点共角速度的节点个数;父节点;半径;与参照点的相对大小vector<pair<int,bool> >e[N];//bool为真时表示共角速度,反之为共线速度bool vis[N];int Log(int k){ int res=0; while(k!=1){ k/=2; res++; } return res;}inline bool cmp(const pair<int,bool>& q,const pair<int,bool>& w){ if(q.second!=w.second) return q.second; return q.first>w.first;}void dfs(int last,int now,int bias){ f[now]=(last==-1?now:last); id[now]=st++; bel[now]=cnt; sz[now]=1; rsz[now]=1; bs[now]=bias; for(int i=0;i<e[now].size();i++) if(!vis[e[now][i].first]&&e[now][i].first!=last){ vis[e[now][i].first]=true; dfs(now,e[now][i].first,bias+(e[now][i].second?0:r[now]-r[e[now][i].first])); sz[now]+=sz[e[now][i].first]; rsz[now]+=(e[now][i].second?1:0)*sz[e[now][i].first]; }}void Build(int ps,int i,int l,int r){ root[ps][i].l=l; root[ps][i].r=r; root[ps][i].tag=root[ps][i].v=0; if(l==r) return ; int mid=l+r>>1; Build(ps,i<<1,l,mid); Build(ps,i<<1|1,mid+1,r);}inline void PushUp(int ps,int i){ root[ps][i].v=max(root[ps][i<<1].v,root[ps][i<<1|1].v);}inline void PushDown(int ps,int i){ if(root[ps][i].tag){ root[ps][i<<1].v+=root[ps][i].tag; root[ps][i<<1].tag+=root[ps][i].tag; root[ps][i<<1|1].v+=root[ps][i].tag; root[ps][i<<1|1].tag+=root[ps][i].tag; root[ps][i].tag=0; }}void Ist(int ps,int i,int x,int val){ if(root[ps][i].l==x&&root[ps][i].r==x){ root[ps][i].v=val; return ; } if(x<=root[ps][i<<1].r) Ist(ps,i<<1,x,val); else if(root[ps][i<<1|1].l<=x) Ist(ps,i<<1|1,x,val); PushUp(ps,i);}void Update(int ps,int i,int l,int r,int bias){ if(l>r) return ; if(l<=root[ps][i].l&&root[ps][i].r<=r){ root[ps][i].v+=bias; root[ps][i].tag+=bias; return ; } PushDown(ps,i); if(l<=root[ps][i<<1].r) Update(ps,i<<1,l,r,bias); if(root[ps][i<<1|1].l<=r) Update(ps,i<<1|1,l,r,bias); PushUp(ps,i);}int Query(int ps,int i,int l,int r){ if(l<=root[ps][i].l&&root[ps][i].r<=r) return root[ps][i].v; PushDown(ps,i); if(r<=root[ps][i<<1].r) return Query(ps,i<<1,l,r); else if(root[ps][i<<1|1].l<=l) return Query(ps,i<<1|1,l,r); else return max(Query(ps,i<<1,l,r),Query(ps,i<<1|1,l,r));}int main(){ int cas=1,a,x,y; while(scanf("%d %d %d",&n,&m,&q)==3){ memset(vis,false,sizeof vis); root.clear(); cnt=0; for(int i=1;i<=n;i++){ e[i].clear(); scanf("%d",&r[i]); r[i]=Log(r[i]); } for(int i=1;i<=m;i++){ scanf("%d %d %d",&a,&x,&y); a--; e[x].push_back(make_pair(y,a)); e[y].push_back(make_pair(x,a)); } for(int i=1;i<=n;i++) sort(e[i].begin(),e[i].end(),cmp); for(int i=1;i<=n;i++) if(!vis[i]){ vis[i]=true; st=1; dfs(-1,i,0); root.push_back(vector<Node>(sz[i]<<2)); Build(cnt++,1,1,sz[i]); } for(int i=1;i<=n;i++) Ist(bel[i],1,id[i],bs[i]); printf("Case #%d:\n",cas++); while(q--){ scanf("%d %d %d",&a,&x,&y); t=Log(y); if(a==1){ if(f[x]==x||(id[f[x]]<id[x]&&id[x]<id[f[x]]+rsz[f[x]])) Update(bel[x],1,id[x]+rsz[x],id[x]+sz[x]-1,t-r[x]);//更新与该节点共线速度的子节点 else Update(bel[x],1,id[x],id[x]+rsz[x]-1,r[x]-t);//更新与该节点共角速度的子节点 r[x]=t; }else printf("%.3f\n",log(2.0)*(t-Query(bel[x],1,id[x],id[x])+Query(bel[x],1,1,root[bel[x]][1].r))); } } return 0;}
阅读全文
0 0
- HDU 6039 Gear Up(2017 Multi-University Training Contest 1)
- HDU 6039 Gear up 2017 Multi-University Training Contest
- 2013 Multi-University Training Contest 1 Warm up HDU 4612
- HDU 3068 2017 Multi-University Training Contest
- HDU 6034 & 2017 Multi-University Training Contest
- hdu 6034 2017 Multi-University Training Contest
- HDU 3065 2017 Multi-University Training Contest
- HDU 6047 2017 Multi-University Training Contest
- HDU 6052 2017 Multi-University Training Contest
- HDU 6058 2017 Multi-University Training Contest
- HDU 6078 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest 1
- 2017 Multi-University Training Contest 1
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- gSoap下Server端接口函数的数据传出
- 机器学习测试题
- 阶乘之和--NYOJ---91(贪心)
- CentOS 安装WildFly Jboss10
- SQL加强(一)概念
- HDU 6039 Gear Up(2017 Multi-University Training Contest 1)
- 算法题:输入aaaabbbcccccc输出a4b3c6。
- 【C++标准模板库笔记1】C++的模板技术
- C++三大特性——多态
- thinkphp3.2 后台获取app前端多个图片上传及参数 的接口写法(upload()函数)
- 关于Javaemail发送邮件时遇到的问题
- selenium server运行报错
- mybatis入门基础(七)----延迟加载
- java排序算法