hdu 6039 Gear Up
题
OvO http://acm.hdu.edu.cn/showproblem.php?pid=6039
(2017 Multi-University Training Contest 1 1007)
解
诶嘿嘿 终于过了
我还以为像我这么菜过这题要用很久呢
结果真的用了很久……淦。
用wi代表i的角速度,ri代表i的角度,则共享线速度的两个齿轮x,y的角速度满足log2(wx)+log2(rx)==log2(wy)+log2(ry)
必然是要对这些齿轮建树的,最后建出来一个森林,然后每个森林取根节点为对照,则整棵树的速度都可以以此为参照用上面那个等式推导出来
然后把节点分2类,一类是他有父亲的(树中,这个节点的上方,有齿轮和他共享线速度),一类是他没父亲的(树中,这个节点的上方,没有齿轮),前者和后者修改半径的话,对子树的影响是不一样的。
1.修改前者的半径话,他共轴的节点为根的子树以及他本身的角速度会发生改变
2.后者的话,以他为根的子树(不包括他)角速度会发生改变
之后就是按DFS序建一颗线段树(区间最值)
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #define log2(x) log(x)/log(2) #define pow2(x) pow(2,x) using namespace std; const int M=1e5+44; struct Edge { int u,v,d; }; int n,m,q,r[M]; int fa[M]; int l1[M],r1[M],l2[M],r2[M]; int init_val[M]; int now; int frt[M],chg[M]; vector<int> v[M]; vector<Edge> edge[M]; int tree[M*3],tag[M*3]; void build(int rt,int li,int ri) { tag[rt]=0; if(li==ri) { tree[rt]=init_val[ri]; return ; } int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1; build(lc,li,mid); build(rc,mid+1,ri); tree[rt]=max(tree[lc],tree[rc]); } void pushdown(int rt,int li,int ri) { if(li==ri) { tag[rt]=0; return ; } int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1; tree[lc]+=tag[rt]; tree[rc]+=tag[rt]; tag[lc]+=tag[rt]; tag[rc]+=tag[rt]; tag[rt]=0; } void update(int rt,int li,int ri,int lq,int rq,int val) //add { if(lq<=li && ri<=rq) { tag[rt]+=val; tree[rt]+=val; return ; } int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1; if(tag[rt]) pushdown(rt,li,ri); if(mid>=lq) update(lc,li,mid,lq,rq,val); if(mid+1<=rq) update(rc,mid+1,ri,lq,rq,val); tree[rt]=max(tree[lc],tree[rc]); } int query(int rt,int li,int ri,int lq,int rq) //get max { int ret=-1e9-7; if(lq<=li && ri<=rq) return tree[rt]; int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1; if(tag[rt]) pushdown(rt,li,ri); if(mid>=lq) ret=max(ret,query(lc,li,mid,lq,rq)); if(mid+1<=rq) ret=max(ret,query(rc,mid+1,ri,lq,rq)); return ret; } int fff(int x) { if(fa[x]==x) return x; fa[x]=fff(fa[x]); return fa[x]; } void init() { int i,j; now=0; for(i=1;i<=n;i++) { l2[i]=1e9+7; r2[i]=0; edge[i].clear(); v[i].clear(); fa[i]=i; } memset(frt,0,(n+4)*sizeof(int)); memset(chg,0,(n+4)*sizeof(int)); } void dfs(int rt,int pa,int dis,int root) { int i,j,uu,vv,dd; l1[rt]=++now+1; frt[rt]=root; init_val[now]=dis; for(i=0;i<edge[rt].size();i++) { uu=edge[rt][i].u; vv=edge[rt][i].v; dd=edge[rt][i].d; if(vv==pa) { chg[uu]=1; continue; } l2[uu]=min(l2[uu],now+1); // cout<<uu<<' '<<vv<<' '<<dd<<endl; dfs(vv,rt,dis+dd,root); r2[uu]=max(r2[uu],now); } r1[rt]=now; } int main() { // freopen("数据//1007.in","r",stdin); // freopen("数据//1007my.out","w",stdout); int i,j,typ,a,b,cas=0,pa,pb; while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init(); for(i=1;i<=n;i++) { scanf("%d",&r[i]); r[i]=log2(r[i]); } for(i=1;i<=m;i++) { scanf("%d%d%d",&typ,&a,&b); if(typ==1) { v[a].push_back(b); v[b].push_back(a); } else fa[fff(a)]=fff(b); } for(i=1;i<=n;i++) for(j=0;j<v[i].size();j++) edge[fff(i)].push_back(Edge{i,fff(v[i][j]),r[i]-r[v[i][j]]}); for(i=1;i<=n;i++) if(fa[i]==i && frt[i]==0) dfs(i,-1,0,i); build(1,1,now); // for(i=1;i<=n;i++) // printf("%d %d - %d %d %d %d - %d\n",frt[i],chg[i],l1[i],r1[i],l2[i],r2[i],init_val[i]); printf("Case #%d:\n",++cas); while(q--) { scanf("%d%d%d",&typ,&a,&b); if(typ==1) { b=log2(b); pa=fff(a); if(chg[a]) { if(l1[pa]-1<=r1[pa]) update(1,1,now,l1[pa]-1,r1[pa],+r[a]-b); if(l2[a]<=r2[a]) update(1,1,now,l2[a],r2[a],-(+r[a]-b)); } else { if(l2[a]<=r2[a]) update(1,1,now,l2[a],r2[a],-r[a]+b); } r[a]=b; } else { pa=fff(a); double ans=1.0*query(1,1,now,l1[frt[pa]]-1,r1[frt[pa]])-query(1,1,now,l1[pa]-1,l1[pa]-1)+log2(b); printf("%.3lf\n",ans*log(2)); } } } return 0; }