值得注意的是:

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

/**************************************************************
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. iOS最笨的办法实现无限轮播图(网络加载)

    iOS最笨的办法实现无限轮播图(网络加载) 简单的做了一下: 使用方法: 把 请求返回的 图片地址(字符串类型)放进数组中就行 可以使用SDWebImage(我就是用的这个)等..需要自己导入并引用, ...

  2. USB-HID鼠标、键盘通讯格式(转) 与本人实际测试结果

    内容为网络转载,如有版权问题请联系删除 USB鼠标键盘协议介绍. 鼠标发送给PC的数据每次4个字节:BYTE1 BYTE2 BYTE3 BYTE4.定义分别是:BYTE1 -- |--bit7:    ...

  3. 星球大战starwar(并查集)

    1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5253  Solved: 2395[Submit ...

  4. [原创]关于absolute、relative和float的一些思考

    absolute: 元素完全脱离文档流,不占文档流的位置,不使用top.left等属性时,仍然在原文档流位置上(但是不在文档流中,也不占用位置),设置了top.left等之后,向上寻找到第一个非sta ...

  5. [ubuntu]安装adobe air

    修改安装文件为可执行权限: sudo ./AdobeAIRInstaller.bin 提示错误: <code> Adobe AIR could not be installed. Inst ...

  6. Delphi 对话框实现源码分析

    Delphi 对话框实现源码分析   简介 在这篇文章中,我将大概的从Delphi XE2 的Dialogs单元入手,分析ShowMessage,MessageBox等对话框运行原理,希望能帮助你理解 ...

  7. 在函数中如何获取 线程对象、线程唯一ID

    threading.current_thread() threading.current_thread().ident

  8. python学习-3.一些常用模块用法

    一.time.datetime 时间戳转化为元组 1 >>> time.localtime() 2 time.struct_time(tm_year=2016, tm_mon=8, ...

  9. 改善程序与设计的55个具体做法 day7

    条款18:让接口容易被正确使用,不易被误用 这里说的接口是广义上的接口,即包括但不限于函数接口.类接口.template接口等,每一种接口都是客户与你的代码进行交互的手段. 我们对客户的所谓“资质或水 ...

  10. 3.06课·········C#语言基础

    Main函数: static void Main(string [] args){ }程序代码需要写在Main函数的花括号内. 一.输出:Console.WriteLine("这是我的第一个 ...