SDOI2014 旅行

题目链接:戳我

真激动。。我这等蒟蒻竟然竟然A了数据结构题

树剖+动态开点线段树

就是给每一个信仰建立一颗线段树。。然后发现空间开不下,就动态开点qwqwq,具体我觉得还是看代码更详细。。。。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 100010
#define inf 0x3f3f3f3f
using namespace std;

int n,m,tt,tot,cnt;
int w[MAXN],c[MAXN],head[MAXN<<1],rt[MAXN<<5];
int dfn[MAXN],siz[MAXN],son[MAXN],fa[MAXN],dep[MAXN],id[MAXN],top[MAXN];
char s[10];

struct Node{int ls,rs,sum,maxx;}t[MAXN<<5];
struct Edge{int nxt,to,dis;}edge[MAXN<<1];

inline void add(int from,int to){edge[++tt].nxt=head[from],edge[tt].to=to,head[from]=tt;}

inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}

inline void dfs1(int x,int pre)
{
    fa[x]=pre;
    dep[x]=dep[pre]+1;
    siz[x]=1;
    int maxx=-1;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==pre) continue;
        dfs1(v,x);
        siz[x]+=siz[v];
        if(siz[v]>maxx) maxx=siz[v],son[x]=v;
    }
}

inline void dfs2(int x,int topf)
{
    top[x]=topf;
    id[x]=++tot;
    if(son[x]) dfs2(son[x],topf);
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}

inline void push_up(int x)
{
    t[x].maxx=max(t[t[x].ls].maxx,t[t[x].rs].maxx);
    t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum;
}

inline void update(int &x,int l,int r,int pos,int k)
{
    if(!x) x=++cnt;
    if(l==r) {t[x].maxx=t[x].sum=k;return;}
    int mid=(l+r)>>1;
    if(pos<=mid) update(t[x].ls,l,mid,pos,k);
    else update(t[x].rs,mid+1,r,pos,k);
    push_up(x);
}

inline int query_sum(int x,int l,int r,int ll,int rr)
{
    int cur_ans=0;
    if(ll<=l&&r<=rr) return t[x].sum;
    int mid=(l+r)>>1;
    if(ll<=mid&&t[x].ls) cur_ans+=query_sum(t[x].ls,l,mid,ll,rr);
    if(mid<rr&&t[x].rs) cur_ans+=query_sum(t[x].rs,mid+1,r,ll,rr);
    return cur_ans;
}

inline int query_max(int x,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr) return t[x].maxx;
    int mid=(l+r)>>1,cur_ans=-inf;
    if(ll<=mid&&t[x].ls) cur_ans=max(cur_ans,query_max(t[x].ls,l,mid,ll,rr));
    if(mid<rr&&t[x].rs) cur_ans=max(cur_ans,query_max(t[x].rs,mid+1,r,ll,rr));
    return cur_ans;
}

inline int QUE_SUM(int k,int x,int y)
{
    int cur_ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        cur_ans+=query_sum(rt[k],1,n,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    cur_ans+=query_sum(rt[k],1,n,id[y],id[x]);
    return cur_ans;
}

inline int QUE_MAX(int k,int x,int y)
{
    int cur_ans=-inf;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        cur_ans=max(cur_ans,query_max(rt[k],1,n,id[top[x]],id[x]));
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    cur_ans=max(cur_ans,query_max(rt[k],1,n,id[y],id[x]));
    return cur_ans;
}

inline void print(int x,int l,int r)
{
    if(l==r)
    {
        printf("x=%d pos=%d sum=%d maxx=%d\n",x,l,t[x].sum,t[x].maxx);
        return;
    }
    int mid=(l+r)>>1;
    if(t[x].ls) print(t[x].ls,l,mid);
    if(t[x].rs) print(t[x].rs,mid+1,r);
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]);//w评级 c信仰
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs1(1,1);
    dfs2(1,1);
    for(int i=1;i<=n;i++) update(rt[c[i]],1,n,id[i],w[i]);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%s%d%d",s,&x,&y);
        if(s[1]=='S') //询问评级总和
        {
            printf("%d\n",QUE_SUM(c[x],x,y));
        }
        else if(s[1]=='M') //询问最大值
        {
            printf("%d\n",QUE_MAX(c[x],x,y));
        }
        else if(s[1]=='C')//城市x改信y教
        {
            update(rt[c[x]],1,n,id[x],0);
            update(rt[y],1,n,id[x],w[x]);
            c[x]=y;
        }
        else //城市x评级调整为y
        {
            update(rt[c[x]],1,n,id[x],y);
            w[x]=y;
        }
        // print(rt[1],1,n);puts("");
        // print(rt[2],1,n);puts("");
        // print(rt[3],1,n);puts("");
    }
    return 0;
}
posted @ 2019-03-12 09:47  风浔凌  阅读(114)  评论(0编辑  收藏  举报