[BZOJ2836]魔法树(链剖+dfs序)
来源:互联网 发布:godaddy 域名续费 编辑:程序博客网 时间:2024/04/28 15:22
题目描述
传送门
题解
链剖+dfs序裸题。
强转又搞错了?
代码
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define LL long longconst int max_n=1e5+5;const int max_tree=max_n*4;const int max_m=max_n;LL n,m,x,y,q,u,t,d,N; LL ans;LL tot,point[max_n],nxt[max_m],v[max_m];LL size[max_n],h[max_n],father[max_n],top[max_n],in[max_n],out[max_n],son[max_n];LL sum[max_tree],delta[max_tree];char opt[20];inline void addedge(LL x,LL y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}inline void dfs_1(LL x,LL fa,LL dep){ size[x]=1; h[x]=dep; father[x]=fa; LL maxson=0; for (LL i=point[x];i;i=nxt[i]) if (v[i]!=fa) { dfs_1(v[i],x,dep+1); size[x]+=size[v[i]]; if (size[v[i]]>maxson) { maxson=size[v[i]]; son[x]=v[i]; } }}inline void dfs_2(LL x,LL fa){ if (son[fa]!=x) top[x]=x; else top[x]=top[fa]; in[x]=++N; if (son[x]) dfs_2(son[x],x); for (LL i=point[x];i;i=nxt[i]) if (v[i]!=fa&&v[i]!=son[x]) dfs_2(v[i],x); out[x]=N;}inline void update(LL now){ sum[now]=sum[now<<1]+sum[now<<1|1];}inline void pushdown(LL now,LL l,LL r,LL mid){ if (delta[now]) { sum[now<<1]+=delta[now]*(LL)(mid-l+1); delta[now<<1]+=delta[now]; sum[now<<1|1]+=delta[now]*(LL)(r-mid); delta[now<<1|1]+=delta[now]; delta[now]=0; }}inline void interval_change(LL now,LL l,LL r,LL lrange,LL rrange,LL v){ LL mid=(l+r)>>1; if (lrange<=l&&r<=rrange) { sum[now]+=v*(LL)(r-l+1); delta[now]+=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) interval_change(now<<1,l,mid,lrange,rrange,v); if (mid+1<=rrange) interval_change(now<<1|1,mid+1,r,lrange,rrange,v); update(now);}inline LL query(LL now,LL l,LL r,LL lrange,LL rrange){ LL mid=(l+r)>>1;LL ans=0; if (lrange<=l&&r<=rrange) return sum[now]; pushdown(now,l,r,mid); if (lrange<=mid) ans+=query(now<<1,l,mid,lrange,rrange); if (mid+1<=rrange) ans+=query(now<<1|1,mid+1,r,lrange,rrange); return ans;}int main(){ scanf("%lld",&n); for (LL i=1;i<n;++i) { scanf("%lld%lld",&x,&y); x++; y++; addedge(x,y); } dfs_1(1,0,1); dfs_2(1,0); scanf("%lld",&q); for (LL i=1;i<=q;++i) { scanf("%s",opt); if (opt[0]=='A') { scanf("%lld%lld%lld",&u,&t,&d); ++u; ++t; LL f1=top[u],f2=top[t]; while (f1!=f2) { if (h[f1]<h[f2]) { swap(f1,f2); swap(u,t); } interval_change(1,1,N,in[f1],in[u],d); u=father[f1]; f1=top[u]; } if (in[u]>in[t]) swap(u,t); interval_change(1,1,N,in[u],in[t],d); } else { scanf("%lld",&u); ++u; ans=query(1,1,N,in[u],out[u]); printf("%lld\n",ans); } }}
手工栈
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define LL long longconst int max_n=1e5+5;const int max_tree=max_n*4;const int max_m=max_n;LL n,m,x,y,q,u,t,d,N; LL ans;LL tot,point[max_n],nxt[max_m],v[max_m];LL size[max_n],h[max_n],father[max_n],top[max_n],in[max_n],out[max_n],son[max_n];LL sum[max_tree],delta[max_tree];char opt[20];int stack[max_n],cur[max_n];bool use[max_n];inline void addedge(LL x,LL y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs_1(){ int tmp=0; stack[++tmp]=1;h[1]=1;size[1]=1LL; for (int i=1;i<=n;++i) cur[i]=point[i]; while (tmp) { int x=stack[tmp]; if (cur[x]&&father[x]==v[cur[x]]) cur[x]=nxt[cur[x]]; if (!cur[x]) { --tmp; if (father[x]) { size[father[x]]+=size[x]; if (size[son[father[x]]]<size[x]) son[father[x]]=x; } continue; } int vt=v[cur[x]]; stack[++tmp]=vt; size[vt]=1LL;h[vt]=h[x]+1;father[vt]=x; cur[x]=nxt[cur[x]]; }}void dfs_2(){ int tmp=0; stack[++tmp]=1;top[1]=1;in[1]=++N; for (int i=1;i<=n;++i) cur[i]=point[i]; while (tmp) { int x=stack[tmp]; if (!use[x]) { use[x]=1; int vt=son[x]; if (vt) { stack[++tmp]=vt; in[vt]=++N; top[vt]=top[x]; } continue; } while (cur[x]&&(father[x]==v[cur[x]]||son[x]==v[cur[x]])) cur[x]=nxt[cur[x]]; if (!cur[x]) { int vt=stack[tmp--]; out[vt]=N; } else { int vt=v[cur[x]]; stack[++tmp]=vt; in[vt]=++N; top[vt]=vt; cur[x]=nxt[cur[x]]; } }}inline void update(LL now){ sum[now]=sum[now<<1]+sum[now<<1|1];}inline void pushdown(LL now,LL l,LL r,LL mid){ if (delta[now]) { sum[now<<1]+=delta[now]*(LL)(mid-l+1); delta[now<<1]+=delta[now]; sum[now<<1|1]+=delta[now]*(LL)(r-mid); delta[now<<1|1]+=delta[now]; delta[now]=0; }}inline void interval_change(LL now,LL l,LL r,LL lrange,LL rrange,LL v){ LL mid=(l+r)>>1; if (lrange<=l&&r<=rrange) { sum[now]+=v*(LL)(r-l+1); delta[now]+=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) interval_change(now<<1,l,mid,lrange,rrange,v); if (mid+1<=rrange) interval_change(now<<1|1,mid+1,r,lrange,rrange,v); update(now);}inline LL query(LL now,LL l,LL r,LL lrange,LL rrange){ LL mid=(l+r)>>1;LL ans=0; if (lrange<=l&&r<=rrange) return sum[now]; pushdown(now,l,r,mid); if (lrange<=mid) ans+=query(now<<1,l,mid,lrange,rrange); if (mid+1<=rrange) ans+=query(now<<1|1,mid+1,r,lrange,rrange); return ans;}int main(){ scanf("%lld",&n); for (LL i=1;i<n;++i) { scanf("%lld%lld",&x,&y); x++; y++; addedge(x,y); } dfs_1(); dfs_2(); scanf("%lld",&q); for (LL i=1;i<=q;++i) { scanf("%s",opt); if (opt[0]=='A') { scanf("%lld%lld%lld",&u,&t,&d); ++u; ++t; LL f1=top[u],f2=top[t]; while (f1!=f2) { if (h[f1]<h[f2]) { swap(f1,f2); swap(u,t); } interval_change(1,1,N,in[f1],in[u],d); u=father[f1]; f1=top[u]; } if (in[u]>in[t]) swap(u,t); interval_change(1,1,N,in[u],in[t],d); } else { scanf("%lld",&u); ++u; ans=query(1,1,N,in[u],out[u]); printf("%lld\n",ans); } }}
0 0
- [BZOJ2836]魔法树(链剖+dfs序)
- bzoj2836: 魔法树 树链剖分
- 【bzoj2836】【魔法树】【树链剖分】
- BZOJ2836魔法树
- BZOJ2836: 魔法树
- bzoj2836魔法树 树剖
- bzoj2836 魔法树
- BZOJ 2836: 魔法树 树链剖分+DFS序
- [SHOI2012]魔法树 链剖
- 魔法树
- bzoj 2836: 魔法树(树链剖分)
- noip模拟赛(一)魔法树
- [BZOJ3306]树(dfs序)
- 【SHOI2012】魔法树
- 魔法参数(一)
- 参数魔法(二)
- Python魔法(1)
- FPGA魔法(1)
- Collections在java中的常见用法
- 第十二周 运算符重载之复数类练习
- 网络编程知识(12)--ISO/OSI七层模型和TCP/IP四层网络模型
- 打字练习
- iOS 多线程编程之NSThread
- [BZOJ2836]魔法树(链剖+dfs序)
- UniversalImageLoader源码解读04-内存缓存
- hdu2516——取石子游戏(FIB博弈)
- iOS 多线程编程之NSOperation
- 树——unique-binary-search-trees
- Ubuntu 14.04LTS 安装和配置Bochs
- Box Shadow(阴影)—Css3演示 工具
- iOS CoreLocation框架第一章—— CLLocationManager的使用(包含iOS6,iOS8,iOS9各种变动)
- ## iOS 中用了autolayout遮挡键盘的处理 ##