Codeforces Round 864 (Div. 2) D

102 阅读2分钟

Li Hua has a tree of n vertices and n−1 edges. The root of the tree is vertex 11. Each vertex i has importance ai. Denote the size of a subtree as the number of vertices in it, and the importance as the sum of the importance of vertices in it. Denote the heavy son of a non-leaf vertex as the son with the largest subtree size. If multiple of them exist, the heavy son is the one with the minimum index.

Li Hua wants to perform m operations:

  • "1 x" (1≤x≤n1) — calculate the importance of the subtree whose root is x.
  • "2 x" (2≤x≤n2) — rotate the heavy son of x up. Formally, denote sonx as the heavy son of x, fax as the father of x. He wants to remove the edge between x and fax and connect an edge between sonx and fax. It is guaranteed that x is not root, but not guaranteed that x is not a leaf. If x is a leaf, please ignore the operation.

Suppose you were Li Hua, please solve this problem.

Input

The first line contains 2 integers n,m (2≤n≤105,1≤m≤105) — the number of vertices in the tree and the number of operations.

The second line contains n integers a1,a2,…,an(−109≤ai≤109) — the importance of each vertex.

Next n−1 lines contain the edges of the tree. The i-th line contains two integers ui and vi (1≤ui,vi≤n1, ui≠vi) — the corresponding edge. The given edges form a tree.

Next m lines contain operations — one operation per line. The j-th operation contains two integers tj,xj (tj∈{1,2}, 1≤xj≤n1, xj≠1 if tj=2) — the j-th operation.

Output

For each query "1 x", output the answer in an independent line.

思路: dfs把每一个点对应的值加起来在用set维护每个节点的子节点

代码:


#include <bits/stdc++.h>

using namespace std;

#define int long long


#define x first

#define y second

const int N = 1e5 + 10;

int n,m;

int a[N];

vector<int>edge[N];

map<int,int>mp;

  


class cmp {

public:

bool operator()(const pair<int, int> &a, const pair<int, int> &b) const {

    return a.first == b.first?a.second<b.second:a.first>b.first;

    }

};

struct NOW{

    int fa;

    int num;

    int ans;

}seg[N];

set<pair<int, int>, cmp> se[N];//如此定义即可

void update(int x,int y)
{
    seg[y].fa = x;
    se[x].insert({seg[y].ans, y});
    seg[x].num += seg[y].num;
    seg[x].ans += seg[y].ans;
}
void build(int u)
{
    mp[u]++;
    for(int i = 0;i < edge[u].size();i ++)
    {
        if(!mp[edge[u][i]])
        {
            build(edge[u][i]);
            update(u,edge[u][i]);
        }
    }
}

void solve()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    {
        cin >> a[i];
        seg[i].num = a[i];
        seg[i].ans = 1;
    }
    for(int i = 1;i < n;i ++)
    {
        int x,y;
        cin >> x >> y;
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    build(1);
    for(int i = 1;i <= m;i ++)
    {
        int op,x;
        cin >> op >> x;
        if(op == 1)
        {
            cout << seg[x].num << '\n';
        }
        else
        {
            if(se[x].size() == 0)
            continue;
            int father = seg[x].fa;
            auto point = *se[x].begin();
            se[father].erase({seg[x].ans, x});
            se[x].erase(point);
            int res = seg[x].ans - seg[point.y].ans;
            seg[point.y].ans = seg[x].ans;
            seg[x].ans = res;
            se[father].insert({seg[point.y].ans, point.y});
            se[point.y].insert({seg[x].ans, x});
            seg[point.y].fa = father;
            seg[x].fa = point.y;
            int sum = seg[x].num - seg[point.y].num;
            seg[x].num -= seg[point.y].num;
            seg[point.y].num += sum;
        }
    }
}

signed main()
{
    int tt = 1;
    //sc(tt);
    while(tt--)
    {
        solve();

    }

}