[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