> 文章列表 > D. Li Hua and Tree(set操作)

D. Li Hua and Tree(set操作)

D. Li Hua and Tree(set操作)

Problem - D - Codeforces

 

李华有一个有n个顶点和n -1条边的树。树的根是顶点1。每个顶点i的重要性为a。将子树的大小表示为该子树中顶点的数量,将重要性表示为该子树中顶点的重要性之和。将非叶顶点的重子结点表示为具有最大子树大小的子结点。如果存在多个重子,则重子的指数最小。李华想做m个操作:“1 x”(1≤x≤n) -计算根为x的子树的重要性。"2 x"(2≤x≤n) -旋转z的重子。形式上,表示son为a的重子,fa为z的父亲。他想去掉和fa之间的边,并在son和fa之间连接一条边。可以保证z不是根结点,但不能保证z不是叶结点。如果是叶,请忽略该操作。假设你是李华,请解决这个问题。输入第一行包含2个整数n, m (2<n <105, 1 < m <105) -树中的顶点数和操作数。第二行包含n个整数a1, a2,…, an(-10°< ai < 10°)-每个顶点的重要性。接下来的n -1行包含树的边。第i行包含两个整数ui和vi (1 < ui, vi≤n, ui vi) -对应的边。给定的边构成了一棵树。接下来的m行包含操作——每行一个操作。第j个操作包含两个整数tj, 2;(t, E [1,2), 1 S a;<n, xj 1如果t;= 2) -第j次操作。输出对于每个“1 æ”查询,在独立的行中输出答案。例子

Examples

input

Copy

7 4
1 1 1 1 1 1 1
1 2
1 3
2 4
2 5
3 6
6 7
1 6
2 3
1 6
1 2

output

Copy

2
3
3

input

Copy

10 14
-160016413 -90133231 -671446275 -314847579 -910548234 121155052 -359359950 83112406 -704889624 145489303
1 6
1 10
10 8
1 4
3 4
2 7
2 5
3 2
9 8
1 4
2 2
2 4
1 4
1 10
2 10
1 9
1 6
2 8
2 10
1 5
1 8
1 1
2 5

output

Copy

-2346335269
-314847579
-476287915
-704889624
121155052
-1360041415
228601709
-2861484545

题解:

纯模拟,只能说看懂题意就很简单

对于操作1,就是输出子树权值和,

操作2,说的很麻烦,简单来说就是

找到这个节点x的父节点f,找到这个节点x的子节点ne(包含最多子节点的节点,如果最大的有一样的,找标号最小的)

找到后f与x断开,f与ne连边,ne与x连边

对于子树权值和,很好计算,

关键是如何找到这个节点x的子节点ne(包含最多子节点的节点,如果最大的有一样的,找标号最小的)

因此对于每个节点,dfs记录每个子树权值的同时,并且记录子树大小

我们利用set进行存储每个节点的子节点,{-son[x],x}

-son[x],每次可以取出节点最多的子节点,同时set保证了下标从小到大,每次取首位即可

接下来就是维护,三个节点子树权值,子树大小,父节点(麻烦,但是很容易理解,代码中均有体现)

(如果操作2操作的是叶子结点,记得按题中所说的跳过)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int long long
vector<int> p[100050];
int n,m;
int sum[100050];
int son[100060];
int fa[100050];
int a[100050];
set <PII> d[100050];
void dfs(int x,int la)
{sum[x] = a[x];son[x] = 1;for(auto ne:p[x]){if(ne == la)continue;dfs(ne,x);sum[x] += sum[ne];son[x] += son[ne];fa[ne] = x;d[x].insert({-son[ne],ne});}
}
void solve()
{cin >> n >> m;for(int i = 1;i <= n;i++){cin >> a[i]; }for(int i = 1;i < n;i++){int l,r;cin >> l >> r;p[l].push_back(r);p[r].push_back(l);}dfs(1,0);while(m--){int op,x;cin >> op >> x;if(op == 1){cout << sum[x] <<"\\n";}else{if(son[x] == 1)continue;int f = fa[x];auto it = d[x].begin();int ne = (*it).second;d[f].erase({-son[x],x});sum[x] -= sum[ne];son[x] -= son[ne];d[x].erase(*it);d[ne].insert({-son[x],x});fa[ne] = f;fa[x] = ne;sum[ne] += sum[x];son[ne] += son[x];d[f].insert({-son[ne],ne});}}
}signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);int t = 1;
//	cin >> t;while(t--){solve(); }
}