【SDOI 2014】 旅行

【题目链接】

           点击打开链接

【算法】

          树链剖分

          每个宗教建一棵线段树,注意数据量大,要动态开点

【代码】

           

#include<bits/stdc++.h>
using namespace std;
#define MAXLOG 18
const int MAXN = 1e5 + 10;
const int MAXS = 1e7 + 10;

int i,n,q,x,y,t,Lca,SZ,timer;
int w[MAXN],c[MAXN],son[MAXN],dfn[MAXN],top[MAXN],size[MAXN],anc[MAXN][MAXLOG],
        dep[MAXN],fa[MAXN],lc[MAXS],rc[MAXS],sum[MAXS],Max[MAXS],root[MAXN];
vector<int> e[MAXN];
char opt[5];

inline void dfs1(int x)
{
        int i,y;
        anc[x][0] = fa[x];
        for (i = 1; i < MAXLOG; i++)
        {
                if (dep[x] < (1 << i)) break;
                anc[x][i] = anc[anc[x][i-1]][i-1]; 
        }
        size[x] = 1;
        for (i = 0; i < e[x].size(); i++)
        {
                y = e[x][i];
                if (fa[x] != y)
                {
                        dep[y] = dep[x] + 1; 
                        fa[y] = x;
                        dfs1(y);
                        size[x] += size[y];
                        if (size[y] > size[son[x]]) son[x] = y;
                }    
        }    
}
inline void dfs2(int x,int tp)
{
        int i,y;
        dfn[x] = ++timer;
        top[x] = tp;
        if (son[x]) dfs2(son[x],tp);
        for (i = 0; i < e[x].size(); i++)
        {
                y = e[x][i];
                if (fa[x] != y && son[x] != y) dfs2(y,y);
        }
}
inline int lca(int x,int y)
{
        int i,t;
        if (dep[x] > dep[y]) swap(x,y);
        t = dep[y] - dep[x];
        for (i = 0; i < MAXLOG; i++)
        {
                if (t & (1 << i))
                        y = anc[y][i];    
        }    
        if (x == y) return x;
        for (i = MAXLOG - 1; i >= 0; i--)
        {
                if (anc[x][i] != anc[y][i])
                {
                        x = anc[x][i];
                        y = anc[y][i];
                }
        }
        return fa[x];
}
inline void push_up(int root)
{
        Max[root] = max(Max[lc[root]],Max[rc[root]]);
        sum[root] = sum[lc[root]] + sum[rc[root]];
}
inline void modify(int &root,int l,int r,int x,int val)
{
        int mid;
        if (!root) root = ++SZ;
        if (l == r) 
        {
                Max[root] = sum[root] = val;
                return;    
        }    
        mid = (l + r) >> 1;
        if (mid >= x) modify(lc[root],l,mid,x,val);
        else modify(rc[root],mid+1,r,x,val);
        push_up(root);
}
inline int query_max(int root,int l,int r,int ql,int qr)
{
        int mid;    
        if (!root) return 0;
        if (l == ql && r == qr) return Max[root];
        mid = (l + r) >> 1;
        if (mid >= qr) return query_max(lc[root],l,mid,ql,qr);
        else if (mid + 1 <= ql) return query_max(rc[root],mid+1,r,ql,qr);
        else return max(query_max(lc[root],l,mid,ql,mid),query_max(rc[root],mid+1,r,mid+1,qr)); 
}
inline int query_sum(int root,int l,int r,int ql,int qr)
{
        int mid;
        if (!root) return 0;
        if (l == ql && r == qr) return sum[root];
        mid = (l + r) >> 1;
        if (mid >= qr) return query_sum(lc[root],l,mid,ql,qr);
        else if (mid + 1 <= ql) return query_sum(rc[root],mid+1,r,ql,qr);
        else return query_sum(lc[root],l,mid,ql,mid) + query_sum(rc[root],mid+1,r,mid+1,qr);    
}

inline int solve1(int c,int x,int y)
{
        int ans = 0,
                tx = top[x],ty = top[y];
        while (tx != ty)
        {
                ans = max(ans,query_max(root[c],1,n,dfn[tx],dfn[x]));
                x = fa[tx]; tx = top[x];        
        }    
        ans = max(ans,query_max(root[c],1,n,dfn[y],dfn[x]));
        return ans;
}
inline int solve2(int c,int x,int y)
{
        int ans = 0,
                tx = top[x],ty = top[y];
        while (tx != ty)
        {
                ans += query_sum(root[c],1,n,dfn[tx],dfn[x]);
                x = fa[tx]; tx = top[x];    
        }    
        ans += query_sum(root[c],1,n,dfn[y],dfn[x]);
        return ans;
}

int main() 
{
        
        scanf("%d%d",&n,&q);
        for (i = 1; i <= n; i++) scanf("%d%d",&w[i],&c[i]);
        for (i = 1; i < n; i++)
        {
                scanf("%d%d",&x,&y);
                e[x].push_back(y);
                e[y].push_back(x);    
        }
        dfs1(1); 
        dfs2(1,1);
        for (i = 1; i <= n; i++) modify(root[c[i]],1,n,dfn[i],w[i]);
        while (q--)
        {
                scanf("%s",&opt);
                if (strcmp(opt,"CC") == 0)
                {
                        scanf("%d%d",&x,&y);    
                        modify(root[c[x]],1,n,dfn[x],0);
                        c[x] = y;
                        modify(root[c[x]],1,n,dfn[x],w[x]);
                } 
                if (strcmp(opt,"CW") == 0)
                {
                        scanf("%d%d",&x,&y);
                        modify(root[c[x]],1,n,dfn[x],y);
                        w[x] = y;
                }
                if (strcmp(opt,"QS") == 0)
                {
                        scanf("%d%d",&x,&y);
                        Lca = lca(x,y);
                        t = solve2(c[x],x,Lca) + solve2(c[x],y,Lca);
                        if (c[Lca] == c[x]) t -= w[Lca];
                        printf("%d\n",t);
                } 
                if (strcmp(opt,"QM") == 0)
                {
                        scanf("%d%d",&x,&y);
                        Lca = lca(x,y);
                        printf("%d\n",max(solve1(c[x],x,Lca),solve1(c[x],y,Lca)));
                }
        }
        
        return 0;
    
}

 

posted @ 2018-05-12 11:04  evenbao  阅读(161)  评论(0编辑  收藏  举报