您的位置:首页 > 其它

[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);
}
}
}


总结

数据范围注意一下(强转什么的)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: