【bzoj3531】[SDOI2014]旅行

来源:互联网 发布:2011年网络春晚 编辑:程序博客网 时间:2024/05/10 08:22

裸树剖+动态开点线段树.
第一次写动态开点线段树,感觉写了主席树的build+普通线段树的query,其实蛮简单的,以前钊神推荐过,有机会还是多写写.

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>using namespace std;const int N=100010;char s[3];int qx,n,m,te,sz,q,tot;int num[N],size[N],tree[N],val[N],w[N],c[N];int head[N],son[N],fa[N],h[N],tp[N],root[N];struct edge{    int v,next;}e[200010];struct seg{    int sum,mx;    int l,r,lch,rch;}tr[2000010];inline int F(){    register int aa,bb;register char ch;    while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);    while(ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;}void add(int u,int v){    e[++te].v=v;    e[te].next=head[u];    head[u]=te;}void dfs1(int x){    size[x]=1;    for (int i=head[x];i;i=e[i].next)    {        int v=e[i].v;        if (v==fa[x])continue;        fa[v]=x;        h[v]=h[x]+1;        dfs1(v);        size[x]+=size[v];        if (size[v]>size[son[x]])son[x]=v;    }}void dfs2(int x,int chain){    tp[x]=chain;    num[x]=++sz;    if (!son[x])return;    dfs2(son[x],chain);    for (int i=head[x];i;i=e[i].next)    {        int v=e[i].v;        if (v==fa[x]||v==son[x])continue;        dfs2(v,v);    }}void updata(int k){    tr[k].sum=tr[tr[k].lch].sum+tr[tr[k].rch].sum;    tr[k].mx=max(tr[tr[k].lch].mx,tr[tr[k].rch].mx);}void build(int &k,int l,int r,int x,int v){    int mid=(l+r)>>1;    if(!k)k=++tot;    tr[k].l=l,tr[k].r=r;    if (l==r)    {        tr[k].sum=v;        tr[k].mx=v;        return;    }    if (x<=mid)build(tr[k].lch,l,mid,x,v);    else build(tr[k].rch,mid+1,r,x,v);    updata(k); }void querysum(int k,int x,int y){    int l=tr[k].l,r=tr[k].r;    if (!k)return;    if (x<=l&&r<=y)    {        qx+=tr[k].sum;        return;    }    int mid=(l+r)>>1;    if (x<=mid)querysum(tr[k].lch,x,y);    if (y>mid)querysum(tr[k].rch,x,y);}void querymax(int k,int x,int y){    int l=tr[k].l,r=tr[k].r;    if (!k)return;    if (x<=l&&r<=y)    {        qx=max(qx,tr[k].mx);        return;    }    int mid=(l+r)>>1;//  getchar();//  cout<<k<<' '<<x<<' '<<y<<' '<<l<<' '<<r<<' '<<mid<<endl;    if (x<=mid)querymax(tr[k].lch,x,y);    if (y>mid)querymax(tr[k].rch,x,y);}int solvesum(int x,int y,int st){    qx=0;    while(tp[x]!=tp[y])    {        if (h[tp[x]]<h[tp[y]])swap(x,y);        querysum(root[st],num[tp[x]],num[x]);        x=fa[tp[x]];    }    if (num[x]>num[y])swap(x,y);    querysum(root[st],num[x],num[y]);    return qx;}int solvemax(int x,int y,int st){    qx=0;    while(tp[x]!=tp[y])    {        if (h[tp[x]]<h[tp[y]])swap(x,y);//      cout<<111111111<<endl;        querymax(root[st],num[tp[x]],num[x]);        x=fa[tp[x]];    }    if (num[x]>num[y])swap(x,y);//  cout<<22222222<<endl;    querymax(root[st],num[x],num[y]);    return qx;}int main(){    int u,v,x,C,y;    n=F(),q=F();    for(int i=1;i<=n;++i)    w[i]=F(),c[i]=F();    for (int i=1;i<n;++i)    u=F(),v=F(),add(u,v),add(v,u);    h[1]=1;dfs1(1);dfs2(1,1);    for (int i=1;i<=n;++i)    build(root[c[i]],1,n,num[i],w[i]);     for (int i=1;i<=q;++i)    {        scanf("%s",s);x=F(),y=F();        if (s[0]=='C'&&s[1]=='C')        {            build(root[c[x]],1,n,num[x],0);            build(root[y],1,n,num[x],w[x]);            c[x]=y;        }        else if (s[0]=='C'&&s[1]=='W')        {            build(root[c[x]],1,n,num[x],y);            w[x]=y;        }        else if (s[0]=='Q'&&s[1]=='S')        printf("%d\n",solvesum(x,y,c[x]));        else if (s[0]=='Q'&&s[1]=='M')        printf("%d\n",solvemax(x,y,c[x]));    }}
0 0
原创粉丝点击