[BZOJ4034][HAOI2015]树上操作(链剖+dfs序)
2016-03-21 11:41
351 查看
题目描述
传送门题解
一上午就调些傻逼题,最近数据结构老是写挂心里很不爽。fye告诉我说多写写就不会错了。傻逼链剖+dfs序,但是后来全改成LL才过了。也不知道为什么。学姐说LL和int必须强转,否则会出错。
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cstdio> using namespace std; #define N 100005 #define LL long long int n,m,opt,x,y,z,dfs_clock; int tot,point ,nxt[N*2],v[N*2]; int a ,num ,father ,son ,size ,h ,in ,out ,top ; LL sum[N*4],delta[N*4],ans; void add(int x,int y) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; } void dfs_1(int x,int fa) { father[x]=fa;size[x]=1;h[x]=h[fa]+1; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { dfs_1(v[i],x); size[x]+=size[v[i]]; if (size[v[i]]>size[son[x]]) son[x]=v[i]; } } void dfs_2(int x,int fa) { if (son[fa]==x) top[x]=top[fa]; else top[x]=x; in[x]=++dfs_clock;num[dfs_clock]=a[x]; if (son[x]) dfs_2(son[x],x); for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa&&v[i]!=son[x]) dfs_2(v[i],x); out[x]=dfs_clock; } void update(int now) { sum[now]=sum[now<<1]+sum[now<<1|1]; } void build(int now,int l,int r) { int mid=(l+r)>>1; if (l==r) { sum[now]=(LL)num[l]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now); } void pushdown(int now,int l,int r,int 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]=0LL; } } void change(int now,int l,int r,int lr,int rr,int v) { int mid=(l+r)>>1; if (lr<=l&&r<=rr) { sum[now]+=(LL)v*(r-l+1); delta[now]+=(LL)v; return; } pushdown(now,l,r,mid); if (lr<=mid) change(now<<1,l,mid,lr,rr,v); if (mid+1<=rr) change(now<<1|1,mid+1,r,lr,rr,v); update(now); } LL query(int now,int l,int r,int lr,int rr) { int mid=(l+r)>>1; LL ans=0LL; if (lr<=l&&r<=rr) return sum[now]; pushdown(now,l,r,mid); if (lr<=mid) ans+=query(now<<1,l,mid,lr,rr); if (mid+1<=rr) ans+=query(now<<1|1,mid+1,r,lr,rr); return ans; } LL ask(int u,int t) { int f1=top[u],f2=top[t]; LL ans=0LL; while (f1!=f2) { if (h[f1]<h[f2]) { swap(f1,f2); swap(u,t); } ans+=query(1,1,n,in[f1],in[u]); u=father[f1]; f1=top[u]; } if (in[u]>in[t]) swap(u,t); ans+=query(1,1,n,in[u],in[t]); return ans; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y),add(y,x); } dfs_1(1,0); dfs_2(1,0); build(1,1,n); for (int i=1;i<=m;++i) { scanf("%d",&opt); if (opt==1) { scanf("%d%d",&x,&z); change(1,1,n,in[x],in[x],z); } if (opt==2) { scanf("%d%d",&x,&z); change(1,1,n,in[x],out[x],z); } if (opt==3) { scanf("%d",&x); ans=ask(1,x); printf("%I64d\n",ans); } } }
手工栈
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cstdio> using namespace std; #define N 100005 #define LL long long int n,m,opt,x,y,z,dfs_clock; int tot,point ,nxt[N*2],v[N*2]; int a ,num ,father ,son ,size ,h ,in ,out ,top ; int stack ,cur ;bool use ; LL sum[N*4],delta[N*4],ans; void add(int x,int y) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; } void dfs_1() { int tmp=0;stack[++tmp]=1; size[1]=1;h[1]=1; for (int i=1;i<=n;++i) cur[i]=point[i]; while (tmp) { int x=stack[tmp]; while (cur[x]&&v[cur[x]]==father[x]) cur[x]=nxt[cur[x]]; if (!cur[x]) { --tmp; if (father[x]) { size[father[x]]+=size[x]; if (size[x]>size[son[father[x]]]) son[father[x]]=x; } continue; } int vt=v[cur[x]];stack[++tmp]=vt; father[vt]=x;size[vt]=1;h[vt]=h[x]+1; cur[x]=nxt[cur[x]]; } } void dfs_2() { int tmp=0;stack[++tmp]=1; top[1]=1;in[1]=++dfs_clock;num[dfs_clock]=a[1]; for (int i=1;i<=n;++i) cur[i]=point[i]; while (tmp) { int x=stack[tmp]; if (!use[x]) { use[x]=1; if (son[x]) { int vt=son[x]; top[vt]=top[x];in[vt]=++dfs_clock;num[dfs_clock]=a[vt]; stack[++tmp]=vt; } continue; } while (cur[x]&&(v[cur[x]]==father[x]||v[cur[x]]==son[x])) cur[x]=nxt[cur[x]]; if (!cur[x]) { --tmp; out[x]=dfs_clock; continue; } int vt=v[cur[x]];stack[++tmp]=vt; top[vt]=vt;in[vt]=++dfs_clock;num[dfs_clock]=a[vt]; cur[x]=nxt[cur[x]]; } } void update(int now) { sum[now]=sum[now<<1]+sum[now<<1|1]; } void build(int now,int l,int r) { int mid=(l+r)>>1; if (l==r) { sum[now]=(LL)num[l]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now); } void pushdown(int now,int l,int r,int 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]=0LL; } } void change(int now,int l,int r,int lr,int rr,int v) { int mid=(l+r)>>1; if (lr<=l&&r<=rr) { sum[now]+=(LL)v*(r-l+1); delta[now]+=(LL)v; return; } pushdown(now,l,r,mid); if (lr<=mid) change(now<<1,l,mid,lr,rr,v); if (mid+1<=rr) change(now<<1|1,mid+1,r,lr,rr,v); update(now); } LL query(int now,int l,int r,int lr,int rr) { int mid=(l+r)>>1; LL ans=0LL; if (lr<=l&&r<=rr) return sum[now]; pushdown(now,l,r,mid); if (lr<=mid) ans+=query(now<<1,l,mid,lr,rr); if (mid+1<=rr) ans+=query(now<<1|1,mid+1,r,lr,rr); return ans; } LL ask(int u,int t) { int f1=top[u],f2=top[t]; LL ans=0LL; while (f1!=f2) { if (h[f1]<h[f2]) { swap(f1,f2); swap(u,t); } ans+=query(1,1,n,in[f1],in[u]); u=father[f1]; f1=top[u]; } if (in[u]>in[t]) swap(u,t); ans+=query(1,1,n,in[u],in[t]); return ans; } int main() { freopen("input.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y),add(y,x); } dfs_1(); dfs_2(); build(1,1,n); for (int i=1;i<=m;++i) { scanf("%d",&opt); if (opt==1) { scanf("%d%d",&x,&z); change(1,1,n,in[x],in[x],z); } if (opt==2) { scanf("%d%d",&x,&z); change(1,1,n,in[x],out[x],z); } if (opt==3) { scanf("%d",&x); ans=ask(1,x); printf("%I64d\n",ans); } } }
总结
数据范围注意一下(强转什么的)。相关文章推荐
- Android TextView特殊效果
- 排序算法之插入排序
- 第八章 网络的时代—网络开发(3)
- 面试贴:java异常小结
- jmock2.5基本教程(转)
- Facebook 新闻(Facebook Journalism)
- 编译安装nginx-1.9.12
- 242. Valid Anagram
- 插入排序法 附测试程序
- Eclipse中syso 快捷键 Alt + / 设置
- VS2013快速安装教程
- 解决 “fatal error C1083: ”无法打开包括文件
- Spring MVC原理图
- PHP进阶:使用session来存储用户的登录信息
- 机器学习算法库scikit-learn的安装
- 使用Spinner实现下拉列表
- iOS-OC-监听键盘的高度 隐藏和出现
- HTML+CSS基础(网页示范)
- 优步刷单这种事,还是不要想了…
- Linux内核分析作业第五周