zoukankan      html  css  js  c++  java
  • CodeChef DGCD Dynamic GCD

    CodeChef题面

    - Time limit 210 ms
    • Code length Limit //内存限制也不说一下,真是的……
      50000 B

    • OS
      Linux

    • Language limit
      C, CPP14, JAVA, PYTH, PYTH 3.6, CS2, PAS fpc, PAS gpc, RUBY, PHP, GO, NODEJS, HASK, SCALA, D, PERL, FORT, WSPC, ADA, CAML, ICK, BF, ASM, CLPS, PRLG, ICON, SCM qobi, PIKE, ST, NICE, LUA, BASH, NEM, LISP sbcl, LISP clisp, SCM guile, JS, ERL, TCL, PERL6, TEXT, PYP3, CLOJ, FS

    • Author
      yellow_agony

    • Tester
      laycurse

    • Tags
      hard, heavy-light, july12, number-theory, yellow_agony

    • Editorial
      http://discuss.codechef.com/problems/DGCD

    感想

    树上动态gcd的第三题也好了。

    解题思路

    树剖套线段树。线段树维护区间gcd见 小z的加油站

    另外,注意这题所有点的下标从0开始。

    源代码

    #include<stdio.h>
    #include<algorithm>
    
    const int MAXN=5e5+5;
    int n,m;
    
    struct Edge{
    	int nxt,to;
    }e[MAXN<<1];
    int cnt=1,head[MAXN];
    inline void add(int u,int v)
    {
    	e[cnt]={head[u],v};
    	head[u]=cnt++;
    	e[cnt]={head[v],u};
    	head[v]=cnt++;
    }
    
    struct Tree{
    	int w;
    	int fa,dep,sz,wson;
    	int top,id;
    }t[MAXN];
    void dfs1(int u,int fa)
    {
    	t[u].fa=fa;
    	t[u].dep=t[fa].dep+1;
    	t[u].sz=1;
    	int maxn=0;
    	for(int i=head[u];i;i=e[i].nxt)
    	{
    		int v=e[i].to;
    		if(v==fa) continue;
    		dfs1(v,u);
    		int temp=t[v].sz;
    		t[u].sz+=temp;
    		if(temp>maxn)
    		{
    			t[u].wson=v;
    			maxn=temp;
    		}
    	}
    }
    int id=1;
    int a[MAXN];
    void dfs2(int u,int top)
    {
    	t[u].top=top;
    	t[u].id=id;
    	a[id]=t[u].w;
    	id++;
    	if(t[u].sz==1) return;
    	dfs2(t[u].wson,top);
    	for(int i=head[u];i;i=e[i].nxt)
    	{
    		int v=e[i].to;
    		if(v==t[u].fa||v==t[u].wson) continue;
    		dfs2(v,v);
    	}
    }
    
    int gcd(int a,int b)
    {
    	if(a<0) a=-a;
    	if(b<0) b=-b;
    	return b?gcd(b,a%b):a;
    }
    
    struct Segtree{
    	int sum,g;//差分后的sum和gcd
    }s[MAXN<<2];
    inline void pushup(int x)
    {
    	s[x]={s[x<<1].sum+s[x<<1|1].sum,gcd(s[x<<1].g,s[x<<1|1].g)};
    }
    void build(int x,int l,int r)//建树前的差分交给主函数
    {
    	if(l==r)
    	{
    		s[x]={a[l],a[l]};
    		return;
    	}
    	int mid=l+r>>1;
    	build(x<<1,l,mid);
    	build(x<<1|1,mid+1,r);
    	pushup(x);
    }
    void update(int x,int l,int r,int pos,int k)//单点修改,增加k
    {
    	if(l==r)
    	{
    		s[x].sum+=k;
    		s[x].g+=k;
    		return;
    	}
    	int mid=l+r>>1;
    	if(pos<=mid) update(x<<1,l,mid,pos,k);
    	else update(x<<1|1,mid+1,r,pos,k);
    	pushup(x);
    }
    int quegcd(int x,int l,int r,int ql,int qr)
    {
    	if(ql<=l&&r<=qr)
    		return s[x].g;
    	int mid=l+r>>1;
    	if(qr<=mid)
    		return quegcd(x<<1,l,mid,ql,qr);
    	else if(ql>mid) return quegcd(x<<1|1,mid+1,r,ql,qr);
    	else return gcd(quegcd(x<<1,l,mid,ql,qr) , quegcd(x<<1|1,mid+1,r,ql,qr));
    }
    int quesum(int x,int l,int r,int ql,int qr)
    {
    	if(ql<=l&&r<=qr)
    		return s[x].sum;
    	int mid=l+r>>1;
    	if(qr<=mid)
    		return quesum(x<<1,l,mid,ql,qr);
    	else if(ql>mid) return quesum(x<<1|1,mid+1,r,ql,qr);
    	else return quesum(x<<1,l,mid,ql,qr) + quesum(x<<1|1,mid+1,r,ql,qr);
    }
    
    
    int optf(int u,int v)
    {
    	int ans=0,l,r,temp;
    	while(t[u].top!=t[v].top)
    	{
    		if(t[t[u].top].dep<t[t[v].top].dep) std::swap(u,v);
    		l=t[t[u].top].id;
    		r=t[u].id;
    		temp=quesum(1,1,n,1,l);
    		if(l!=r) temp=gcd(quegcd(1,1,n,l+1,r),temp);
    		if(!ans) ans=temp;
    		else ans=gcd(temp,ans);
    		u=t[t[u].top].fa;
    	}
    	if(t[u].id>t[v].id) std::swap(u,v);
    	l=t[u].id,r=t[v].id;
    	temp=quesum(1,1,n,1,l);
    	if(l!=r) temp=gcd(quegcd(1,1,n,l+1,r),temp);
    	if(!ans) ans=temp;
    	else ans=gcd(temp,ans);
    	return ans;
    }
    
    void optc(int u,int v,int d)
    {
    	int l,r;
    	while(t[u].top!=t[v].top)
    	{
    		if(t[t[u].top].dep<t[t[v].top].dep) std::swap(u,v);
    		l=t[t[u].top].id;
    		r=t[u].id;
    		update(1,1,n,l,d);
    		if(r<n) update(1,1,n,r+1,-d);
    		u=t[t[u].top].fa;
    	}
    	if(t[u].id>t[v].id) std::swap(u,v);
    	l=t[u].id,r=t[v].id;
    	update(1,1,n,l,d);
    	if(r<n) update(1,1,n,r+1,-d);
    }
    
    
    int main()
    {
    	freopen("test.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=1,u,v;i<n;i++)
    	{
    		scanf("%d%d",&u,&v);
    		u++,v++;//下标全部增加1
    		add(u,v);
    	}
    	for(int i=1;i<=n;i++)
    		scanf("%d",&t[i].w);
    	dfs1(1,0);
    	dfs2(1,1);
    	for(int i=n;i>1;i--) a[i]-=a[i-1];
    	build(1,1,n);
    	scanf("%d",&m);
    	while(m--)
    	{
    		char opt[3];
    		int u,v,d;
    		scanf("%s%d%d",opt,&u,&v);
    		u++,v++;//下标全部增加1
    		if(opt[0]=='F')
    		{
    			printf("%d
    ",optf(u,v));
    		}
    		else
    		{
    			scanf("%d",&d);
    			optc(u,v,d);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    photoshop--图像大小(分辨率和宽高)
    Arduino--单向倾斜开关
    禁止google浏览器http链接强制跳转为https
    属性缓存_使用ConcurrentDictionary替代Hashtable对多线程的对象缓存处理
    .Net(windows服务器)清理缓存数据的几个方法
    【西天取经】(升级.net5)用了一整天才把项目从.netcoreapp3.1升级到.net5(转载)
    在Debian 9 vim中启用鼠标复制粘贴
    将数据批量插入SQL Server
    shell 脚本中 在grep -E '($wo|$ni|$ta)' 这里面用变量
    kubernetes 重启的几种方法
  • 原文地址:https://www.cnblogs.com/wawcac-blog/p/11321076.html
Copyright © 2011-2022 走看看