[BZOJ4034][HAOI2015]树上操作(链剖+dfs序)
来源:互联网 发布:英雄岛全套源码下载 编辑:程序博客网 时间:2024/04/29 22:32
题目描述
传送门
题解
一上午就调些傻逼题,最近数据结构老是写挂心里很不爽。fye告诉我说多写写就不会错了。
傻逼链剖+dfs序,但是后来全改成LL才过了。也不知道为什么。学姐说LL和int必须强转,否则会出错。
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cstdio>using namespace std;#define N 100005#define LL long longint n,m,opt,x,y,z,dfs_clock;int tot,point[N],nxt[N*2],v[N*2];int a[N],num[N],father[N],son[N],size[N],h[N],in[N],out[N],top[N];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 longint n,m,opt,x,y,z,dfs_clock;int tot,point[N],nxt[N*2],v[N*2];int a[N],num[N],father[N],son[N],size[N],h[N],in[N],out[N],top[N];int stack[N],cur[N];bool use[N];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); } }}
总结
数据范围注意一下(强转什么的)。
0 0
- [BZOJ4034][HAOI2015]树上操作(链剖+dfs序)
- 【bzoj4034】[HAOI2015]树上操作(树链剖分+dfs序)
- [bzoj4034][HAOI2015]树上操作 dfs序+树状数组
- 【树链剖分(DFS序)+线段树】BZOJ4034(HAOI2015)[树上操作]题解
- BZOJ4034(HAOI2015)[树上操作]--线段树+DFS序
- bzoj4034 [HAOI2015]树上操作
- 【bzoj4034】[HAOI2015]树上操作
- BZOJ4034: [HAOI2015]树上操作
- [bzoj4034][HAOI2015]树上操作
- bzoj4034: [HAOI2015]树上操作
- 【BZOJ4034】【HAOI2015】树上操作
- bzoj4034 [HAOI2015]树上操作
- bzoj4034: [HAOI2015]树上操作
- BZOJ4034 [HAOI2015]树上操作
- 【BZOJ4034】树上操作(HAOI2015)-树链剖分
- BZOJ4034: [HAOI2015]树上操作(洛谷P3178)
- 【bzoj4034】【HAOI2015】【树上操作】【树链剖分】
- 【HAOI2015】【BZOJ4034】树上操作T2
- 机器学习算法库scikit-learn的安装
- Eclipse中syso 快捷键 Alt + / 设置
- 集合的概念、类型、接口以及接口的实现类的方法描述
- 242. Valid Anagram
- 插入排序法 附测试程序
- [BZOJ4034][HAOI2015]树上操作(链剖+dfs序)
- Java并发编程(一)——线程
- 浅谈Java中的hashcode方法
- 时间复杂度和空间复杂度详解
- Android更改桌面应用程序launcher的两种方式
- FormAuthenticationFilter无效的解决方案
- webview总结
- C#中DropDownList显示默认值
- 2016.03.21 java web摘抄