CC DGCD:Dynamic GCD——题解
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——题解的更多相关文章
- CodeChef DGCD Dynamic GCD
CodeChef题面 Time limit 210 ms Code length Limit //内存限制也不说一下,真是的-- 50000 B OS Linux Language limit C, ...
- 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- ...
- HDU5726:GCD——题解
题目:hdu的5726 (我原博客的东西,正好整理过来,属于st表裸题) (可以看出我当时有多么的菜--) 这道题写了一遍,然而蒟蒻的我的时间爆炸了-- 于是看了一下学长的代码(顺便在此处%一下学长) ...
- 洛谷 P2568 GCD 题解
原题链接 庆祝一下:数论紫题达成成就! 第一道数论紫题.写个题解庆祝一下吧. 简要题意:求 \[\sum_{i=1}^n \sum_{j=1}^n [gcd(i,j)==p] \] 其中 \(p\) ...
- CodeChef Dynamic GCD
嘟嘟嘟vjudge 我今天解决了一个历史遗留问题! 题意:给一棵树,写一个东西,支持一下两种操作: 1.\(x\)到\(y\)的路径上的每一个点的权值加\(d\). 2.求\(x\)到\(y\)路径上 ...
- BZOJ2820:YY的GCD——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2820 Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x& ...
- BZOJ1901:Zju2112 Dynamic Rankings——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序 ...
- Dynamic Gcd
树链剖分+差分 直接区间加显然是不行的,由于gcd(a,b,c)=gcd(a,a-b,b-c),那么我们对这些数差分,然后就变成单点修改.原本以为这道题很简单,没想到这么麻烦,就膜了发代码. 首先我们 ...
- CH 4302 Interval GCD 题解
题意 给定一个长度为N的数列A,以及M条指令 (N≤5* 10^5, M<=10^5),每条指令可能是以下两种之一: "C l r d",表示把 A[l],A[l+1],-, ...
随机推荐
- Qt-QML-C++交互实现文件IO系统-后继-读取XML文件和创建XML文件
在前面两篇中,大致完成了一个文件IO的读和写操作.前面两篇文章链接 http://blog.csdn.net/z609932088/article/details/71488250 http://bl ...
- 怎样从Java转换到Kotlin代码:现在就开始使用Kotlin(KAD 29)
作者:Antonio Leiva 时间:Jul, 4, 2017 原文链接:https://antonioleiva.com/kotlin-from-java/ Kotlin最神奇特性之一是它能与Ja ...
- Java小记(1)
return 关键字 package mytest; public class Test4 { public static void main(String[] args) { // TODO Aut ...
- Java 递归 反射 正则表达式
一 递归 1. 就是函数自身调用自身 (就是在栈内存中不断的加载同一个函数) 2. 什么时候用递归呢? 当一个功能被重复使用 而每一次使用该功能时的参数不确定 都由上次的功能元素结果来确定 简单说: ...
- Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis
第5章--MyBatis MyBatis入门 Abstract: 数据库框架的工作原理和使用方法(以MyBatis为例) 面向对象的世界与关系型数据库的鸿沟: 面向对象世界中的数据是对象: 关系型数据 ...
- 57[LeetCode] Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...
- 菜鸟之路——机器学习之决策树个人理解及Python实现
最近开始学习机器学习,以下会记录我学习中遇到的问题以及我个人的理解 决策树算法,网上很多介绍,在这不复制粘贴.下面解释几个关键词就好. 信息熵(entropy):就是信息不确定性的多少 H(x)=-Σ ...
- Solidity中的基本类型转换
Solidity中的基本类型转换(十四)|入门系列 2017/4/29 posted in Solidity入门系列 点击查看原文,获得优化的排版. 隐式转换 如果一个运算符能支持不同类型.编译器会隐 ...
- scatter注记词2
couch ranch bind ski extra bring note embrace tape they stick legend
- rsync+inotify实现实时同步,自动触发同步文件
本文参考来自:http://chocolee.blog.51cto.com/8158455/1400596 我的需求和他的略有不同,同时做了一下更改,如下: 需求:两台机器相互为主备,搭建相同的两个服 ...