zoukankan      html  css  js  c++  java
  • 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
    ",frt[i],chg[i],l1[i],r1[i],l2[i],r2[i],init_val[i]);
    		printf("Case #%d:
    ",++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
    ",ans*log(2));
    			} 
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    RDLC报表中浮点型设置精度设置小数位位数
    C# 设置DateTime类型的变量值等于Null
    我的2011就这样混掉了
    RDLC报表改动的注意事项之增加字段和参数
    (分享)C# 绘制统计图(柱状图, 折线图, 扇形图)
    C#实现Winform自定义半透明遮罩层
    C#中判断网络连接的状态
    su 和 sudo、su root和su root 区别
    嵌入式系统软件优化方法
    ARM开发步步深入之定时加速
  • 原文地址:https://www.cnblogs.com/FxxL/p/7260031.html
Copyright © 2011-2022 走看看