https://vjudge.net/problem/CodeChef-DGCD

https://www.codechef.com/problems/DGCD

题目大意:

给一颗带点权的树,两个操作:

1.将两点间最短路上的点权+d

2.查询两点间最短路上的点权的GCD

显然又是树链剖分,点这里看树链剖分原理

但是我们发现一个问题,我们虽然可以建立线段树维护GCD,但是没有办法处理区间修改问题。

我们考虑更相减损之术的原理,两数做差后的结果和小数的GCD=原来的GCD。

所以我们在维护单点权值的同时维护相邻点权的差值,则GCD(区间内所有相邻点权差的GCD,区间首位点权)就是我们要查的值。

虽然这么说很简单,但是有很多具体细节,大体比较难解决的比如:

1.修改区间的时候,单点权值要用lazy标记维护,而相邻点权的差值就单点修改两次(注意:有些情况下也可能只有一次)即可。

2.询问的时候,单点权值单点查询即可,相邻点权的差值区间查询,注意区间长度为点数-1,也就是说我们可能会碰到空区间,特判掉。

其余具体操作请看代码。

#include<cstdio>
#include<iostream>
using namespace std;
const int N=;
const int INF=;
/*============================**
*************基本操作************
**============================*/
inline int read(){
int X=,w=;char ch=;
while(ch<''||ch>''){w|=ch=='-';ch=getchar();}
while(ch>=''&&ch<='')X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int to;
int nxt;
}edge[*N];
struct tree{
int lazy;
int d;
int v;
}t[*N];
int head[N],cnt=,n;
inline void add(int u,int v){
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
inline int abs(int x){
return x>?x:-x;
}
int gcd(int x,int y){
return y?gcd(y,x%y):abs(x);
}
int fa[N],dep[N],size[N],son[N],top[N],pos[N],idx[N];
int val[N];
/*============================**
*************树链剖分************
**============================*/
void dfs1(int u){
size[u]=;
for(int i=head[u];i;i=edge[i].nxt){
   int v=edge[i].to;
   if(v==fa[u])continue;
   fa[v]=u;dep[v]=dep[u]+;
   dfs1(v);
     size[u]+=size[v];
   if(!son[u]||size[v]>size[son[u]])son[u]=v;
}
return;
}
int tot;
void dfs2(int u,int anc){
   tot++;
   pos[u]=tot;
   idx[tot]=u;
   top[u]=anc;
   if(!son[u])return;
   dfs2(son[u],anc);
   for(int i=head[u];i;i=edge[i].nxt){
   int v=edge[i].to;
   if(v==fa[u]||v==son[u])continue;
   dfs2(v,v);
}
return;
}
inline void init(){
dfs1();
top[]=idx[]=pos[]=;
tot=;
dfs2(,);
return;
}
/*============================**
************传递lazy************
**============================*/
inline void pushdown(int a,bool is_leaf){
if(is_leaf){
   t[a].v+=t[a].lazy;
}else{
   t[a*].lazy+=t[a].lazy;
   t[a*+].lazy+=t[a].lazy;
}
t[a].lazy=;
return;
}
/*============================**
*************建树操作************
**============================*/
void build(int a,int l,int r){
if(l==r){
   t[a].v=val[idx[l]];
   t[a].d=val[idx[l]]-val[idx[l-]];
   return;
}
int mid=(l+r)>>;
build(a*,l,mid);
build(a*+,mid+,r);
t[a].d=gcd(t[a*].d,t[a*+].d);
return;
}
/*============================**
*************查询操作************
**============================*/
int point_query(int a,int l,int r,int k){
pushdown(a,(l==r));
if(l==r){
   return t[a].v;
}
int mid=(l+r)>>;
if(k<=mid)return point_query(a*,l,mid,k);
return point_query(a*+,mid+,r,k);
}
int range_query(int a,int l,int r,int l1,int r1){
if(l1>r1)return ;
if(r<l1||r1<l)return ;
if(l1<=l&&r<=r1){
   return t[a].d;
}
int mid=(l+r)>>;
return gcd(range_query(a*,l,mid,l1,r1),range_query(a*+,mid+,r,l1,r1));
}
int path_query(int u,int v){
if(top[u]!=top[v]){
   if(dep[top[u]]<dep[top[v]]){int t=u;u=v;v=t;}
   if(top[u]!=u)
   return gcd(path_query(fa[top[u]],v),gcd(range_query(,,n,pos[son[top[u]]],pos[u]),point_query(,,n,pos[top[u]])));
   return gcd(path_query(fa[top[u]],v),point_query(,,n,pos[top[u]]));
}
if(dep[u]>dep[v]){int t=u;u=v;v=t;}
if(u!=v)
   return gcd(point_query(,,n,pos[u]),range_query(,,n,pos[son[u]],pos[v]));
return point_query(,,n,pos[u]);
}
/*============================**
*************修改操作************
**===========================**/
void point_modi(int a,int l,int r,int k,int c){
if(l==r){
   t[a].d+=c;
   return;
}
int mid=(l+r)>>;
if(k<=mid)point_modi(a*,l,mid,k,c);
else point_modi(a*+,mid+,r,k,c);
t[a].d=gcd(t[a*].d,t[a*+].d);
return;
}
void range_modi(int a,int l,int r,int l1,int r1,int v){
if(r1<l||r<l1)return;
pushdown(a,(l==r));
if(l1<=l&&r<=r1){
   t[a].lazy+=v;
   return;
}
int mid=(l+r)>>;
range_modi(a*,l,mid,l1,r1,v);
range_modi(a*+,mid+,r,l1,r1,v);
return;
}
void path_modi(int u,int v,int c){
if(top[u]!=top[v]){
  if(dep[top[u]]<dep[top[v]]){int t=u;u=v;v=t;}
  point_modi(,,n,pos[top[u]],c);
   if(son[u]!=u)point_modi(,,n,pos[son[u]],-c);
   range_modi(,,n,pos[top[u]],pos[u],c);
   path_modi(fa[top[u]],v,c);
   return;
}
if(dep[u]>dep[v]){int t=u;u=v;v=t;}
point_modi(,,n,pos[u],c);
if(son[v])point_modi(,,n,pos[son[v]],-c);
range_modi(,,n,pos[u],pos[v],c);
return;
}
/*============================**
*************主程序段************
**============================*/
int main(){
n=read();
for(int i=;i<=n;i++){
   int u=read()+;
  int v=read()+;
  add(u,v);
   add(v,u);
}
for(int i=;i<=n;i++)val[i]=read();
init();
build(,,n);
int q=read();
while(q--){
char op=;
while(op!='F'&&op!='C')op=getchar();
  if(op=='C'){
   int a=read()+;
   int b=read()+;
   int c=read();
   path_modi(a,b,c);
  }else{
   int a=read()+;
   int b=read()+;
   printf("%d\n",path_query(a,b));
   }
}
return ;
}

CC DGCD:Dynamic GCD——题解的更多相关文章

  1. CodeChef DGCD Dynamic GCD

    CodeChef题面 Time limit 210 ms Code length Limit //内存限制也不说一下,真是的-- 50000 B OS Linux Language limit C, ...

  2. 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- ...

  3. HDU5726:GCD——题解

    题目:hdu的5726 (我原博客的东西,正好整理过来,属于st表裸题) (可以看出我当时有多么的菜--) 这道题写了一遍,然而蒟蒻的我的时间爆炸了-- 于是看了一下学长的代码(顺便在此处%一下学长) ...

  4. 洛谷 P2568 GCD 题解

    原题链接 庆祝一下:数论紫题达成成就! 第一道数论紫题.写个题解庆祝一下吧. 简要题意:求 \[\sum_{i=1}^n \sum_{j=1}^n [gcd(i,j)==p] \] 其中 \(p\) ...

  5. CodeChef Dynamic GCD

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

  6. BZOJ2820:YY的GCD——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2820 Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x& ...

  7. BZOJ1901:Zju2112 Dynamic Rankings——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901 Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序 ...

  8. Dynamic Gcd

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

  9. CH 4302 Interval GCD 题解

    题意 给定一个长度为N的数列A,以及M条指令 (N≤5* 10^5, M<=10^5),每条指令可能是以下两种之一: "C l r d",表示把 A[l],A[l+1],-, ...

随机推荐

  1. Unity Container中的几种注册方式与示例

    1.实例注册 最简单的注册方式就是实例注册,Unity 容器负责维护对一个类型的单例引用,比如: 有如下的实际类型: namespace ConsoleSample { public class Sa ...

  2. 拼接index

    import MySQLdb import sys db = MySQLdb.connect(host="127.0.0.1", # your host, usually loca ...

  3. VS中添加新项 数据选项卡下没有ADO.NET实体数据模型解决方案

    第一种:C:\ProgramData下面搜索EFTools找到你vs对应版本的EFTools.msi 先remove 然后再Install 重启电脑再看 第二种:如果意外地删除了 Visual Stu ...

  4. git配置github链接

    1.百度git官网-下载最新版git 2.一路默认下一步安装 3.打开 git bash here 命令行 4.注册github账号(用自己的邮箱就可以,不会英文可以用谷歌翻译)注册成功后建立项目 5 ...

  5. git基础(2)

    三.查看提交历史日志查看·提交历史:git log 命令一个常用的选项是 -p,用来显示每次提交的内容差异. 你也可以加上 -2 来仅显示最近两次提交如果你想看到每次提交的简略的统计信息,你可以使用 ...

  6. JMeter自学笔记3-创建自己的第一个测试用例

    一.写在前面的话: 上篇我们已经认识了JMeter的图形界面,大家应该都是很懵的.那么这篇,我们将学习使用JMeter创建第一个属于自己测试用例. 二.创建自己的第一个测试用例: 1.新建一个Thre ...

  7. Fiddler - 拦截手机请求

    1. 在电脑上安装Fillder. 安装好之后的Fiddler 打开是这样的: 2. 浏览器访问http://127.0.0.1:8888/fiddler,下载证书并安装 3. 打开抓取https请求 ...

  8. jmeter多台压力机测试

    jmeter控制机会自动将脚本发送至压力机 1.控制机配置 jmeter.properties中配置: remote_hosts=ip1:1099,ip2:1022,ip3:1099 将压力机ip+p ...

  9. Spring Cloud(七):配置中心(Git 版与动态刷新)【Finchley 版】

    Spring Cloud(七):配置中心(Git 版与动态刷新)[Finchley 版]  发表于 2018-04-19 |  更新于 2018-04-24 |  Spring Cloud Confi ...

  10. "Generative Adversarial Nets" Notes

    - Ian J.Goodfellow 中文翻译:https://blog.csdn.net/wspba/article/details/54577236 代码实现:https://github.com ...