BZOJ3639 Query on a tree VII

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3639

Query on a tree VII

Description

You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are numbered from 1 to n.

Each node has a color, white or black, and a weight.

We will ask you to perfrom some instructions of the following form:

0 u : ask for the maximum weight among the nodes which are connected to u, two nodes are connected iff all the node on the path from u to v (inclusive u and v) have a same color.

1 u : toggle the color of u(that is, from black to white, or from white to black).

2 u w: change the weight of u to w.

Input

The first line contains a number n denoted how many nodes in the tree(1 ≤ n ≤ 105). The next n - 1 lines, each line has two numbers (u,  v) describe a edge of the tree(1 ≤ u,  v ≤ n).

The next 2 lines, each line contains n number, the first line is the initial color of each node(0 or 1), and the second line is the initial weight, let’s say Wi, of each node(|Wi| ≤ 109).

The next line contains a number m denoted how many operations we are going to process(1 ≤ m ≤ 105). The next m lines, each line describe a operation (t,  u) as we mentioned above(0 ≤ t ≤ 2, 1 ≤ u ≤ n, |w| ≤ 109).

Output

For each query operation, output the corresponding result.

扫描二维码关注公众号,回复: 1865265 查看本文章
Sample Input

5
1 2
1 3
1 4
1 5
0 1 1 1 1
1 2 3 4 5
3
0 1
1 1
0 1

Sample Output

1
5

题目大意

询问同色联通块内的最大值,支持修改颜色,修改权值。

题解

前置知识:维护联通块

Q t r e e 系列,板子题一家。

维护联通块的方法见上面链接,剩下的就是维护一个子树的最大值了。此时,如果仅仅维护左右儿子的最大值,显然是不行的, S p l a y 时也没法继续维护。所以,我们需要给每个节点开一个 m u l t i s e t ,将所有虚子树的最大值都丢进去,就可以做到 O ( l o g 2 n ) 更新了。

其他维护大同小异。

借此学习一波 S T L 姿势。

代码
#include<bits/stdc++.h>
#define ls son[v][0]
#define rs son[v][1]
#define inf INT_MAX
#define C lct[col[a]]
using namespace std;
const int M=1e5+5,N=M<<1;
int col[M],fa[M],val[M],n,m;
vector<int>mmp[M];
struct LCT{
    int son[N][2],dad[N],mx[N];
    multiset<int>s[N];
    LCT(){mx[0]=-inf;}
    bool notroot(int v){return son[dad[v]][0]==v||son[dad[v]][1]==v;}
    void up(int v){mx[v]=max(val[v],max(mx[ls],mx[rs]));if(!s[v].empty())mx[v]=max(mx[v],*s[v].rbegin());}
    void spin(int v)
    {
        int f=dad[v],ff=dad[f],k=son[f][1]==v,w=son[v][!k];
        if(notroot(f))son[ff][son[ff][1]==f]=v;son[v][!k]=f;son[f][k]=w;
        if(w)dad[w]=f;dad[f]=v;dad[v]=ff;up(f);
    }
    void splay(int v)
    {
        int f,ff;
        while(notroot(v))
        {
            f=dad[v];ff=dad[f];
            if(notroot(f))spin((son[f][0]==v)^(son[ff][0]==f)?v:f);
            spin(v);
        }
        up(v);
    }
    void access(int v)
    {for(int f=0;v;v=dad[f=v]){splay(v);if(rs)s[v].insert(mx[rs]);if(rs=f)s[v].erase(s[v].find(mx[f]));up(v);}}
    int root(int v){access(v);splay(v);while(ls)v=ls;splay(v);return v;}
    void link(int v){splay(v);int f=dad[v]=fa[v];access(f);splay(f);son[f][1]=v;up(f);}
    void cut(int v){access(v);splay(v);ls=dad[ls]=0;up(v);}
}lct[2];
void dfs(int v,int f)
{
    fa[v]=f;int to;
    for(int i=mmp[v].size()-1;i>=0;--i)
    {to=mmp[v][i];if(to==f)continue;dfs(to,v);}
    lct[col[v]].link(v);
}
void in()
{
    int a,b;scanf("%d",&n);
    for(int i=1;i<n;++i)scanf("%d%d",&a,&b),mmp[a].push_back(b),mmp[b].push_back(a);
    for(int i=1;i<=n;++i)scanf("%d",&col[i]);
    for(int i=1;i<=n;++i)scanf("%d",&val[i]);
}
void ac()
{
    int op,a;dfs(1,n+1);scanf("%d",&m);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&op,&a);
        switch(op)
        {
            case 0:printf("%d\n",C.mx[C.son[C.root(a)][1]]);break;
            case 1:C.cut(a);col[a]^=1;C.link(a);break;
            case 2:C.access(a);C.splay(a);scanf("%d",&val[a]);C.up(a);
        }
    }
}
int main(){in();ac();}

猜你喜欢

转载自blog.csdn.net/shadypi/article/details/80738680
今日推荐