BZOJ 4034 [HAOI2015]T2 树链剖分+线段树
2015-09-28 08:25
337 查看
题意:
一棵以1为根的树,有n个节点,m个操作。
第一种单点修改。
第二种修改一个点的子树。
第三种询问一个点到根的路径上所有点的权值和。
解析:
看到有人在做我就跑过来看了一下,看完题发现这不SB题么- -
于是就写了下,差点被出题人气死。
TMD 那个 fr , to 难道就是逗我玩的?
你丫fr,to不代表有向边?
这么出题不会掉RP?
改了20分钟就这错了?你逗我?
第一种操作略
第二种操作修改子树…dfs序。
第三种链剖完之后直接找就行了。
复杂度O(nlog^2n);
代码:
一棵以1为根的树,有n个节点,m个操作。
第一种单点修改。
第二种修改一个点的子树。
第三种询问一个点到根的路径上所有点的权值和。
解析:
看到有人在做我就跑过来看了一下,看完题发现这不SB题么- -
于是就写了下,差点被出题人气死。
TMD 那个 fr , to 难道就是逗我玩的?
你丫fr,to不代表有向边?
这么出题不会掉RP?
改了20分钟就这错了?你逗我?
第一种操作略
第二种操作修改子树…dfs序。
第三种链剖完之后直接找就行了。
复杂度O(nlog^2n);
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 100100 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; typedef long long ll; int n,m,cnt,tot; ll a ,val ; int head ; int dep ,son ,fa ,siz ,tim ,end ,top ; struct node { int from,to; int next; }edge[N<<1]; void init() { memset(head,-1,sizeof(head)); cnt=1,dep[1]=1; } void edgeadd(int from,int to) { edge[cnt].from=from,edge[cnt].to=to,edge[cnt].next=head[from]; head[from]=cnt++; } void dfs1(int now) { son[now]=-1,siz[now]=1; for(int i=head[now];i!=-1;i=edge[i].next) { int to=edge[i].to; if(to==fa[now])continue; fa[to]=now; dep[to]=dep[now]+1; dfs1(to); siz[now]+=siz[to]; if(son[now]==-1||siz[son[now]]<siz[to])son[now]=to; } } void dfs2(int now,int tp) { top[now]=tp,tim[now]=++tot; if(son[now]!=-1)dfs2(son[now],tp); for(int i=head[now];i!=-1;i=edge[i].next) { int to=edge[i].to; if(to==son[now]||to==fa[now])continue; dfs2(to,to); } end[now]=tot; } ll sum[N<<2],col[N<<2]; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void pushdown(int rt,int l,int r) { if(col[rt]) { int mid=(l+r)>>1; sum[rt<<1]+=col[rt]*(ll)(mid-l+1); sum[rt<<1|1]+=col[rt]*(ll)(r-mid); col[rt<<1]+=col[rt]; col[rt<<1|1]+=col[rt]; col[rt]=0; } } void build(int l,int r,int rt) { if(l==r) { sum[rt]=val[l]; return; } int mid=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update_pt(int p,ll v,int l,int r,int rt) { if(l==r) { sum[rt]+=v; return; } int mid=(l+r)>>1; pushdown(rt,l,r); if(p<=mid)update_pt(p,v,lson); else update_pt(p,v,rson); pushup(rt); } void update_seg(ll v,int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { col[rt]+=v; sum[rt]+=v*(ll)(r-l+1); return; } int mid=(l+r)>>1; pushdown(rt,l,r); if(L<=mid)update_seg(v,L,R,lson); if(R>mid)update_seg(v,L,R,rson); pushup(rt); } ll query_seg(int L,int R,int l,int r,int rt) { ll ret=0; if(L<=l&&r<=R) { return sum[rt]; } int mid=(l+r)>>1; pushdown(rt,l,r); if(L<=mid)ret+=query_seg(L,R,lson); if(R>mid)ret+=query_seg(L,R,rson); return ret; } ll query(int x) { ll ret=0; while(top[x]) { int l=tim[top[x]],r=tim[x]; ret+=query_seg(l,r,1,n,1); x=fa[top[x]]; } return ret; } int main() { init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); edgeadd(x,y); edgeadd(y,x); } dfs1(1); dfs2(1,1); for(int i=1;i<=n;i++)val[tim[i]]=a[i]; build(1,n,1); for(int i=1;i<=m;i++) { int opt,x; ll a; scanf("%d",&opt); if(opt==1) { scanf("%d%lld",&x,&a); update_pt(tim[x],a,1,n,1); }else if(opt==2) { scanf("%d%lld",&x,&a); update_seg(a,tim[x],end[x],1,n,1); }else { scanf("%d",&x); printf("%lld\n",query(x)); } } }
相关文章推荐
- 我从来没有想要去
- 在 VC6 中使用 GdiPlus-使用
- Kinect v2.0原理介绍之十:获取高清面部帧的AU单元特征保存到文件
- C#基础规则和需要注意的语言特性
- SOA系列之基本特性
- Travelling(spfa+状态压缩dp)
- vs2010中的错误错误C2665: “AfxMessageBox”: 2 个重载中没有一个可以转换所有参数类型和Unicode字符集和多字节字符集关系
- 使用POI插件,提取导出excel的工具类
- jQuery.extend函数源码详解
- 第七届湘计算机程序设计竞赛的学生 报道称,数字游戏
- DOM中文本和标记的插入
- BZOJ 2743 [HEOI2012]采花 离线+线段树
- web:2、httpd的特性和配置详解
- HashMap和HashTable源码学习笔记
- 修改远程桌面端口让win7更安全
- poj1006-Biorhythms(中国剩余定理)
- AspNet MVC4 教育-28:Asp.Net MVC4 Ajax技术部门四舍五入余速Demo
- OpenCV中feature2D学习——ORB和BruteForceMatcher
- 9-25考试第三题解题报告(还是写了指针翻译神马的都是浮云感觉好久不说话连话都不会说了233333333QVO)
- 基于XBee进行ZigBee组网(二)——ZigBee网络与XCTU的使用