值得注意的是:

一个点的子树是存在一起的。。。也就是说我们修改子树的时候只用。。。

/**************************************************************
Problem: 1036
User: Ez3real
Language: C++
Result: Accepted
Time:3068 ms
Memory:8112 kb
****************************************************************/ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define l(x) (x<<1)
#define r(x) ((x<<1)|1)
#define ll long long
using namespace std;
struct Treenode{int l,r;ll tag,val,mx;};
struct Segtree
{
Treenode tr[*];
void pushup(int id){tr[id].val=tr[l(id)].val+tr[r(id)].val;}
void pushdown(int id)
{
tr[l(id)].val+=tr[id].tag*(tr[l(id)].r-tr[l(id)].l+);
tr[r(id)].val+=tr[id].tag*(tr[r(id)].r-tr[r(id)].l+);
tr[l(id)].tag+=tr[id].tag;tr[r(id)].tag+=tr[id].tag;
tr[id].tag=;
}
void build(int id,int L,int R)
{
tr[id].l=L,tr[id].r=R;
tr[id].tag=;
if(L==R)return;
int mid=(L+R)>>;
build(l(id),L,mid);
build(r(id),mid+,R);
pushup(id);
}
void update(int id,int L,int R,ll k)
{
if(tr[id].l>=L && tr[id].r<=R)
{
tr[id].val+=k*(tr[id].r-tr[id].l+);
tr[id].tag+=k;
return;
}
if(tr[id].tag)pushdown(id);
int mid=(tr[id].l+tr[id].r)>>;
if(L<=mid)update(l(id),L,R,k);
if(R>mid) update(r(id),L,R,k);
pushup(id);
}
ll query(int id,int L,int R)
{
if(tr[id].l>=L && tr[id].r<=R)return tr[id].val;
if(tr[id].tag)pushdown(id);
int mid=(tr[id].l+tr[id].r)>>;
ll ans=;
if(L<=mid)ans+=query(l(id),L,R);
if(R>mid)ans+=query(r(id),L,R);
return ans;
}
}Seg; int first[],to[*],next[*];
ll val[*],cnt;
int size[],depth[],fa[],pos[],bl[],sz;
inline void add(int u,int v){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;}
int n,q,r,P;
inline void dfs1(int u)
{
size[u]=;
for(int i=first[u];i;i=next[i])
{
if(to[i]==fa[u])continue;
depth[to[i]]=depth[u]+;
fa[to[i]]=u;
dfs1(to[i]);
size[u]+=size[to[i]];
}
}
inline void dfs2(int u,int idc)
{
int k=;
sz++;
pos[u]=sz;
bl[u]=idc;
for(int i=first[u];i;i=next[i])
if(depth[to[i]]>depth[u] && size[to[i]]>size[k])
k=to[i]; if(k==)return;
dfs2(k,idc);
for(int i=first[u];i;i=next[i])
if(depth[to[i]]>depth[u] && k!=to[i])
dfs2(to[i],to[i]);
}
void tradd(ll x,ll v){Seg.update(,pos[x],pos[x]+size[x]-,v);}
ll trq(ll x){return Seg.query(,pos[x],pos[x]+size[x]-)%P;}
void Chainadd(ll x,ll y,ll v)
{
while(bl[x]!=bl[y])
{
if(depth[bl[x]]<depth[bl[y]]){x^=y;y^=x;x^=y;}
Seg.update(,pos[bl[x]],pos[x],v);
x=fa[bl[x]];
}
if(depth[x]<depth[y]){x^=y;y^=x;x^=y;}
Seg.update(,pos[y],pos[x],v);
}
ll Qsum(ll u,ll v)
{
ll sum=;
while(bl[u]!=bl[v])
{
if(depth[bl[u]]<depth[bl[v]]){u^=v;v^=u;u^=v;}
(sum+=Seg.query(,pos[bl[u]],pos[u]))%=P;
u=fa[bl[u]];
}
if(depth[u]<depth[v]){u^=v;v^=u;u^=v;}
(sum+=Seg.query(,pos[v],pos[u]))%=P;
return sum;
}
void Solve()
{
scanf("%d%d%d%d",&n,&q,&r,&P);
for(int i=;i<=n;i++)scanf("%lld",&val[i]);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
depth[r]=;
dfs1(r);
dfs2(r,r);
Seg.build(,,n);
for(int i=;i<=n;i++)Seg.update(,pos[i],pos[i],val[i]);
for(int i=;i<=q;i++)
{
int opt;
scanf("%d",&opt);
if(opt==)
{
ll x,y,w;
scanf("%lld%lld%lld",&x,&y,&w);
Chainadd(x,y,w);
}
if(opt==)
{
ll x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",Qsum(x,y));
}
if(opt==)
{
ll x,v;
scanf("%lld%lld",&x,&v);
tradd(x,v);
}
if(opt==)
{
ll x;
scanf("%lld",&x);
printf("%lld\n",trq(x));
}
}
}
int main()
{
Solve();
return ;
}

Luogu3384

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define l(x) (x<<1)
#define r(x) ((x<<1)|1)
#define ll long long
using namespace std; struct Treenode{int l,r;ll tag,val,mx;};
struct Segtree
{
Treenode tr[*];
void pushup(int id){tr[id].val=tr[l(id)].val+tr[r(id)].val;tr[id].mx=max(tr[l(id)].mx,tr[r(id)].mx);}
void build(int id,int L,int R)
{
tr[id].l=L,tr[id].r=R;
if(L==R)return;
int mid=(L+R)>>;
build(l(id),L,mid);
build(r(id),mid+,R);
pushup(id);
}
void update(int k,int x,int y)
{
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>;
if(l==r){tr[k].val=tr[k].mx=y;return;}
if(x<=mid)update(k<<,x,y);
else update(k<<|,x,y);
tr[k].val=tr[k<<].val+tr[k<<|].val;
tr[k].mx=max(tr[k<<].mx,tr[k<<|].mx);
}
int query(int id,int L,int R)
{
if(tr[id].l>=L && tr[id].r<=R)return tr[id].val;
int mid=(tr[id].l+tr[id].r)>>;
int ans=;
if(L<=mid)ans+=query(l(id),L,R);
if(R>mid)ans+=query(r(id),L,R);
return ans;
}
int Query(int id,int L,int R)
{
if(tr[id].l>=L && tr[id].r<=R)return tr[id].mx;
int mid=(tr[id].l+tr[id].r)>>;
int ans=-;
if(L<=mid)ans=max(ans,Query(l(id),L,R));
if(R>mid)ans=max(ans,Query(r(id),L,R));
return ans;
}
}Seg; int first[],to[*],next[*],val[*],cnt;
int size[],depth[],fa[],pos[],bl[],sz;
inline void add(int u,int v){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;}
inline void dfs1(int u)
{
size[u]=;
for(int i=first[u];i;i=next[i])
{
if(to[i]==fa[u])continue;
depth[to[i]]=depth[u]+;
fa[to[i]]=u;
dfs1(to[i]);
size[u]+=size[to[i]];
}
}
inline void dfs2(int u,int idc)
{
int k=;
sz++;
pos[u]=sz;
bl[u]=idc;
for(int i=first[u];i;i=next[i])
if(depth[to[i]]>depth[u] && size[to[i]]>size[k])
k=to[i]; if(k==)return;
dfs2(k,idc);
for(int i=first[u];i;i=next[i])
if(depth[to[i]]>depth[u] && k!=to[i])
dfs2(to[i],to[i]);
}
int Qsum(int u,int v)
{
int sum=;
while(bl[u]!=bl[v])
{
if(depth[bl[u]]<depth[bl[v]]){u^=v;v^=u;u^=v;}
sum+=Seg.query(,pos[bl[u]],pos[u]);
u=fa[bl[u]];
}
if(pos[u]>pos[v]){u^=v;v^=u;u^=v;}
sum+=Seg.query(,pos[u],pos[v]);
return sum;
}
int Qmax(int u,int v)
{
int mx=-;
while(bl[u]!=bl[v])
{
if(depth[bl[u]]<depth[bl[v]]){u^=v;v^=u;u^=v;}
mx=max(mx,Seg.Query(,pos[bl[u]],pos[u]));
u=fa[bl[u]];
}
if(pos[u]>pos[v]){u^=v;v^=u;u^=v;}
mx=max(mx,Seg.Query(,pos[u],pos[v]));
return mx;
}
int n,q;
void Solve()
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=;i<=n;i++)scanf("%d",&val[i]);
dfs1();
dfs2(,);
Seg.build(,,n);
for(int i=;i<=n;i++)Seg.update(,pos[i],val[i]);
scanf("%d",&q);
char ch[];
for(int i=;i<=q;i++)
{
int x,y;scanf("%s%d%d",ch,&x,&y);
if(ch[]=='C'){val[x]=y;Seg.update(,pos[x],y);}
else
{
if(ch[]=='M')printf("%d\n",Qmax(x,y));
else printf("%d\n",Qsum(x,y));
}
}
}
int main()
{
Solve();
return ;
}

bzoj1036

洛谷3384&bzoj1036树链剖分的更多相关文章

  1. 洛谷P3979 遥远的国度 树链剖分+分类讨论

    题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...

  2. 洛谷 P4114 Qtree1 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...

  3. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  4. 洛谷.4114.Qtree1(树链剖分)

    题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...

  5. 洛谷 P3384 【模板】树链剖分

    树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...

  6. 树链剖分详解(洛谷模板 P3384)

    洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...

  7. ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】

    题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...

  8. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  9. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

随机推荐

  1. 在mac上独立安装PHP环境

    1.http://dditblog.com/blog_418.html 2.http://www.jianshu.com/p/0456dd3cc78b

  2. Python菜鸟之路:Python基础-生成器和迭代器、递归

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束.迭代器只能往前不会后退. 1. 迭代器优点 对于无法随机访问的数据结构(比如set)而言, ...

  3. Bootstrap第2天

    Bootstrap第2天 解决IE低版本不支持HTML5元素的方法 CSS全局样式--栅格系统 1.栅格系统介绍     Bootstrap提供了一套响应式.移动设备优先的流式的栅格系统.     B ...

  4. 4.对urls.py的解释

    解释: 路由配置文件(URL分发器),它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表.就是以这种方式告诉Django对于每个URL的处理类.Django启动的时候回去加载urls. ...

  5. git本地仓库管理远程仓库

    git remote add origin https://xxxxxgit push -u origin master

  6. Shell传参的多种方式

    Shell 传参的多种方式 使用$1 $2 这种类似占位符的方式 # 命令行调用 start.sh 8080 9090 # 脚本中获取 port1=$1 # 8080 port2=$2 # 9090 ...

  7. rails 注释

    view -# js.erb <%# xxxx %> 单行注释

  8. Python 自定义模块的打包和发布

    写了一个Python模块,要求打包发布,供同事们使用,好吧,查了一下,网上大部分教程没有一个能把话说明白,不过最后还是解决了,特此记录一下, 以免下次遇到同样问题,也帮助其他有缘人,哈哈. 首先看一下 ...

  9. P4844 LJJ爱数数

    题目 P4844 LJJ爱数数 本想找到莫比乌斯反演水题练练,结果直接用了两个多小时才做完 做法 \(\sum\limits_{a=1}^n\sum\limits_{b=1}^n\sum\limits ...

  10. 手机端适配rem代码片段

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...