博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树剖||树链剖分||线段树||BZOJ4034||Luogu3178||[HAOI2015]树上操作
阅读量:5328 次
发布时间:2019-06-14

本文共 3663 字,大约阅读时间需要 12 分钟。

题面:

好像其他人都嫌这道题太容易了懒得讲,好吧那我讲。

题解:第一个操作和第二个操作本质上是一样的,所以可以合并。唯一值得讲的点就是:第二个操作要求把某个节点 x 为根的子树中所有点的点权都增加 a,我们可以发现一个子树中的结点在线段树中会是连续的一段,而这段数最后一个就是seg值(seg数组在Dfs2中有进行预处理,seg[x]:x结点在线段树中的位置)最大的那个。所以可以在Dfs2中多预处理一个tu[x]表示以x为根的子树中seg值最大的结点的seg值。接下来进行操作二时Update(1,seg[x],tu[x])就可以了。总体挺模版的,而且由于询问只询问x到根的和,所以不需要预处理dep数组。记得开ll。

代码:

1 #include
2 #include
3 #include
4 #define ll long long 5 #define max(a,b) ((a)>(b)?(a):(b)) 6 using namespace std; 7 inline ll rd(){ 8 ll x=0,f=1;char c=getchar(); 9 while(c<'0'||c>'9'){
if(c=='-')f=-1; c=getchar();} 10 while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} 11 return f*x; 12 } 13 const ll maxn=100005,maxq=100005; 14 ll N,Q,num_edge=0,edge_head[maxn],W[maxn],a,b,seg[maxn],rev[maxn],fa[maxn]; 15 ll top[maxn],son[maxn],size[maxn],tu[maxn],X,A,Ans,o; 16 struct Edge{ 17 int to,nx; 18 }edge[maxn<<1]; 19 inline void Add_edge(int from,int to){ 20 edge[++num_edge].nx=edge_head[from]; 21 edge[num_edge].to=to; 22 edge_head[from]=num_edge; 23 return; 24 } 25 inline void Dfs1(int x,int f){ 26 fa[x]=f; 27 size[x]=1; 28 for(int i=edge_head[x];i;i=edge[i].nx){ 29 int y=edge[i].to; 30 if(y!=f){ 31 Dfs1(y,x); 32 size[x]+=size[y]; 33 if(size[y]>size[son[x]])son[x]=y; 34 } 35 } 36 return; 37 } 38 inline void Dfs2(int x){ 39 tu[x]=seg[0]; 40 if(son[x]){ 41 int y=son[x]; 42 seg[y]=++seg[0];//seg[x]:x在线段树中的下标 43 rev[seg[0]]=y; 44 top[y]=top[x]; 45 Dfs2(y); 46 tu[x]=max(tu[x],tu[y]); 47 } 48 for(int i=edge_head[x];i;i=edge[i].nx){ 49 int y=edge[i].to; 50 if(top[y]==0){ 51 seg[y]=++seg[0]; 52 rev[seg[0]]=y; 53 top[y]=y; 54 Dfs2(y); 55 tu[x]=max(tu[x],tu[y]); 56 } 57 } 58 return; 59 } 60 struct Tree{ 61 ll sum,l,r,flag; 62 }t[maxn<<3]; 63 inline void Build(int k,int l,int r){ 64 t[k].l=l;t[k].r=r; 65 if(l==r){ 66 t[k].sum=W[rev[l]]; 67 return; 68 } 69 int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1; 70 Build(ls,l,mid);Build(rs,mid+1,r); 71 t[k].sum=t[ls].sum+t[rs].sum; 72 return; 73 } 74 inline void Pushdown(int k){ 75 if(t[k].flag){ 76 int ls=k<<1,rs=k<<1|1,ln=t[ls].r-t[ls].l+1,rn=t[rs].r-t[rs].l+1; 77 t[ls].sum+=t[k].flag*ln;t[rs].sum+=t[k].flag*rn; 78 t[ls].flag+=t[k].flag;t[rs].flag+=t[k].flag; 79 t[k].flag=0; 80 } 81 return; 82 } 83 inline void Update(int k,int ql,int qr,ll s){ 84 int l=t[k].l,r=t[k].r; 85 if(ql<=l&&r<=qr){ 86 t[k].sum+=s*(r-l+1); 87 t[k].flag+=s; 88 return; 89 } 90 Pushdown(k); 91 int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1; 92 if(ql<=mid)Update(ls,ql,qr,s); 93 if(qr>mid)Update(rs,ql,qr,s); 94 t[k].sum=t[ls].sum+t[rs].sum; 95 return; 96 } 97 inline void Query(int k,int ql,int qr){ 98 int l=t[k].l,r=t[k].r; 99 if(ql<=l&&r<=qr){100 Ans+=t[k].sum;101 return;102 }103 Pushdown(k);104 int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1;105 if(ql<=mid)Query(ls,ql,qr);106 if(qr>mid)Query(rs,ql,qr);107 return;108 }109 inline ll Ask(int x){110 int fx=top[x];111 Ans=0;112 while(fx!=1){113 Query(1,seg[fx],seg[x]);114 x=fa[fx];115 fx=top[x];116 }117 Query(1,1,seg[x]);118 return Ans;119 }120 int main(){121 N=rd();Q=rd();122 for(int i=1;i<=N;i++)W[i]=rd();123 for(int i=1;i

By:AlenaNuna

转载于:https://www.cnblogs.com/AlenaNuna/p/10176646.html

你可能感兴趣的文章
(HDU)1089 --A+B for Input-Output Practice (I)(输入输出练习(I))
查看>>
SQL Server 备份和还原
查看>>
Data Structure 基本概念
查看>>
微信内置浏览器不支持 onclick 如何解决?(原因是因为内面中的内容或者标签大部分是动态生成的)...
查看>>
Ubuntu改坏sudoers后无法使用sudo的解决办法
查看>>
记字符编码与转义符的纠缠
查看>>
NEYC 2017 游记
查看>>
【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
查看>>
[搬运] 写给 C# 开发人员的函数式编程
查看>>
对Python中yield的理解
查看>>
NailTech 公司网站制作思路
查看>>
Shiro权限控制框架
查看>>
java第六次作业
查看>>
vsftpd虚拟用户【公司系统部分享】
查看>>
盒子box在网页中居中的方法
查看>>
Python之旅Day14 JQuery部分
查看>>
二十一、 Memento 备忘录(行为型模式)
查看>>
python 3.X中打包二进制数据存储字符串出错原因分析
查看>>
core--线程池
查看>>
B+树介绍
查看>>