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\n",optf(u,v));
}
else
{
scanf("%d",&d);
optc(u,v,d);
}
}
return 0;
}

CodeChef DGCD Dynamic GCD的更多相关文章

  1. codechef Dynamic GCD [树链剖分 gcd]

    Dynamic GCD 题意:一棵树,字词树链加,树链gcd 根据\(gcd(a,b)=gcd(a,a-b)\) 得到\(gcd(a_1, a_2, ..., a_i) = gcd(a_1, a_1- ...

  2. CC DGCD:Dynamic GCD——题解

    https://vjudge.net/problem/CodeChef-DGCD https://www.codechef.com/problems/DGCD 题目大意: 给一颗带点权的树,两个操作: ...

  3. CodeChef Dynamic GCD

    嘟嘟嘟vjudge 我今天解决了一个历史遗留问题! 题意:给一棵树,写一个东西,支持一下两种操作: 1.\(x\)到\(y\)的路径上的每一个点的权值加\(d\). 2.求\(x\)到\(y\)路径上 ...

  4. CodeChef DGCD

    You're given a tree on N vertices. Each vertex has a positive integer written on it, number on the i ...

  5. Dynamic Gcd

    树链剖分+差分 直接区间加显然是不行的,由于gcd(a,b,c)=gcd(a,a-b,b-c),那么我们对这些数差分,然后就变成单点修改.原本以为这道题很简单,没想到这么麻烦,就膜了发代码. 首先我们 ...

  6. CodeChef Sereja and GCD

    Sereja and GCD   Problem code: SEAGCD   Submit All Submissions   All submissions for this problem ar ...

  7. scau 2015寒假训练

    并不是很正规的.每个人自愿参与自愿退出,马哥找题(马哥超nice么么哒). 放假第一周与放假结束前一周 2015-01-26 http://acm.hust.edu.cn/vjudge/contest ...

  8. BZOJ 5028 小z的加油站

    bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...

  9. 洛谷 P4571 BZOJ 2257 [JSOI2009]瓶子和燃料

    bzoj题目链接 上面hint那里是选择第2个瓶子和第3个瓶子 Time limit 10000 ms Memory limit 131072 kB OS Linux Source Jsoi2009 ...

随机推荐

  1. xshell登陆后脚本

    vbs的写法: Sub Main xsh.Screen.Send "ssh 用户名@服务器地址" xsh.Screen.Send VbCr xsh.Screen.WaitForSt ...

  2. Hbase 三维存储

    hbase所谓的三维有序存储的三维是指:rowkey(行主键),column key(columnFamily+qualifier),timestamp(时间戳)三部分组成的三维有序存储. 1.row ...

  3. Git_初步了解

    Git入门篇 一:Git是什么?Git是目前世界上最先进的分布式版本控制系统.工作原理 / 流程: Workspace:工作区Index / Stage:暂存区Repository:仓库区(或本地仓库 ...

  4. 从入门到自闭之Python三大器--迭代器

    函数名的第一类对象(概述): 使用方式: 函数名可以当做值赋值给变量 def func(): print(1) print (func) #查看函数的内存地址 a = func print (a) # ...

  5. 模板 - 强连通分量 - Kosaraju

    Kosaraju算法 O(n+m) vector<int> s; void dfs1(int u) { vis[u] = true; for (int v : g[u]) if (!vis ...

  6. paramiko : 错误集整理

    错误1    时间2017-12-19:No handlers could be found for logger "paramiko.transport" 解决办法:parami ...

  7. 开发跨平台应用解决方案-uniapp 真心不错,支持一波

    uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架,开发者编写一套代码,可编译到iOS.Android.微信小程序等多个平台. 用了mui,H5+一年多了,感觉dcloud 最近推出的 ...

  8. PAT Basic 1076 Wifi密码 (15 分)

    下面是微博上流传的一张照片:“各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1:B-2:C-3:D-4:请同学们自己作答,每两日一 ...

  9. Java并发(基础知识)—— 创建、运行以及停止一个线程

    在计算机世界,当人们谈到并发时,它的意思是一系列的任务在计算机中同时执行.如果计算机有多个处理器或者多核处理器,那么这个同时性是真实发生的:如果计算机只有一个核心处理器那么就只是表面现象. 现代所有的 ...

  10. 模拟赛小结:2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest

    2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest 2019年10月11日 15:35-20:35(Solved 8,Penalty 675 ...