值得注意的是:

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

/**************************************************************
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. Solr6.5创建core

    首先在solrhome(solrhome的路径和配置见中solr的web.xml)http://www.cnblogs.com/paulversion/p/6827949.html 中创建mycore ...

  2. python 基础 9.6 设计表结构

    一. 设计表结构    在操作设计数据库之前,我们先要设计数据库表结构,我们就来分析分析经典的学生,课程,成绩,老师这几者他们之间的关系,我们先来分析各个主体他们直接有什么属性,并确定表结构,在实际开 ...

  3. sql server 2008 去除html标签

    由于商品详情数据库的字段是text,存放的是html,但是要求导出的商品详情中只是商品的描述,不要标签,原来打算先把数据导入excel中,然后利用java的正则去替换,结果由于商品详情太大,一个单元格 ...

  4. 我的Android进阶之旅------>Android之动画之Frame Animation实例

    ============================首先看看官网上关于Frame animation的介绍================================ 地址:http://de ...

  5. 17.Django表单验证

    Django提供了3中方式来验证表单 官网文档:https://docs.djangoproject.com/en/1.9/ref/validators 1.表单字段验证器 a.引入:from dja ...

  6. 12.Django数据库操作(执行原生SQL)

    1.使用extra方法 解释:结果集修改器,一种提供额外查询参数的机制 说明:依赖model模型 用在where后: Book.objects.filter(publisher_id="1& ...

  7. linux环境下redis安装

    本篇文章主要说明的是Linux环境下redis数据库的安装: 首先进入目标目录: 下载安装包,执行命令: wget http://download.redis.io/releases/redis-4. ...

  8. spring项目改名后不能启动的原因及解决办法

    今日修改了一个spring项目的项目名称,修改后启动项目Debug as->Debug on server,过了很久也没有出现web首页,仔细看项目的定时器已经启动,eclipse的Consol ...

  9. Linux基础系列:常用命令(7)_正则表达式

    一.环境边量 每个用户登录shell需要执行的四个文件 /etc/profile /home/egon/.bashrc_profile /home/egon/.bashrc /etc/bashrc 非 ...

  10. LeetCode:汇总区间【228】

    LeetCode:汇总区间[228] 题目描述 给定一个无重复元素的有序整数数组,返回数组区间范围的汇总. 示例 1: 输入: [0,1,2,4,5,7] 输出: ["0->2&quo ...