This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define fast ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
#define MOD 1000000007
#define inf 1e18
#define fi first
#define se second
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FORD(i,a,b) for(int i=a;i>=b;i--)
#define sz(a) ((int)(a).size())
#define endl '\n'
#define pi 3.14159265359
#define TASKNAME "synchronization"
using namespace std;
template<typename T> bool maximize(T &res, const T &val) { if (res < val){ res = val; return true; }; return false; }
template<typename T> bool minimize(T &res, const T &val) { if (res > val){ res = val; return true; }; return false; }
typedef pair<int,int> ii;
typedef pair<int,ii> iii;
typedef vector<int> vi;
/**
Cho 1 cây N đỉnh.
Ta có các thao tác, bật tắt cạnh.
Ta có q truy vấn:
- với đỉnh u, hãy đếm số đỉnh từng cùng thành phần liên thông với u.
Bài này dùng observation:
Khi ta thêm 1 cạnh (u, v) vào kết quả của thành phần liên thông sẽ trở thành:
ans_new = ans[u] + ans[v] - c. c: số thằng mà 2 thằng giống nhau.
Trong đó c là kết quả của lần kết hợp gần nhất (c = 0, nếu chưa từng kết hợp)
Nhưng ta không thể lưu kết quả cho tất cả các nút được nên ta
sẽ lấy 1 nút làm đại diện (nút có độ cao thấp nhất trên cây
**/
struct BinaryIndexedTree{
vector<int> BIT;
BinaryIndexedTree(int sz = 0){
BIT.resize(sz + 9);
}
int get(int id){
int res = 0;
for(int i = id; i > 0; i -= i & (-i)){
res += BIT[i];
}
return res;
}
void update(int id, int x){
for(int i = id; i < BIT.size(); i += i & (-i)){
BIT[i] += x;
}
}
};
const int MAXN = 3e5 + 9;
vector<int> g[MAXN];
ii edge[MAXN];
int n, m, q;
BinaryIndexedTree opt;
int dfsTime = 0;
int del[MAXN], in[MAXN], out[MAXN], depth[MAXN], P[30][MAXN];
int ans[MAXN], ans_edge_before[MAXN];
void dfs(int u, int p){
P[0][u] = p;
in[u] = ++dfsTime;
for(auto id: g[u]){
int v = edge[id].se + edge[id].fi - u;
if (v == p) continue;
depth[v] = depth[u] + 1;
dfs(v, u);
}
out[u] = dfsTime;
}
int jumpKth(int u, int k){
for(int i = 0; k > 0; k >>= 1, i++){
if (k&1) u = P[i][u];
}
return u;
}
int root(int u){
int s = opt.get(in[u]);
int l = 0, r = depth[u], res = 0;
while(l <= r){
int mid = (l + r) >> 1;
if (opt.get(in[ jumpKth(u, mid) ]) == s){
res = mid;
l = mid + 1;
}
else{
r = mid - 1;
}
}
return jumpKth(u, res);
}
void eraseEdge(int u){
opt.update(in[u], 1);
opt.update(out[u] + 1, -1);
}
void addEdge(int u){
opt.update(in[u], -1);
opt.update(out[u] + 1, 1);
}
void updateEdge(int id){
int u = edge[id].se;
int p = root(edge[id].fi);
if (del[id] == 0){
del[id] = 1;
ans[u] = ans[p];
ans_edge_before[id] = ans[p];
}
else{
ans[p] = ans[u] + ans[p] - ans_edge_before[id];
del[id] = 0;
}
if (del[id] == 1) eraseEdge(u);
else addEdge(u);
}
main()
{
fast;
if (fopen(TASKNAME".inp","r")){
freopen(TASKNAME".inp","r",stdin);
freopen(TASKNAME".out","w",stdout);
}
cin >> n >> m >> q;
FOR(i, 1, n - 1){
int u, v;
cin >> u >> v;
edge[i] = {u, v};
g[u].pb(i);
g[v].pb(i);
}
fill(del, del + 1 + n, 1);
dfs(1, -1);
FOR(i, 1, 20){
FOR(j, 1, n){
if (P[i - 1][j] == -1) P[i][j] = -1;
else P[i][j] = P[i - 1][P[i - 1][j]];
}
}
FOR(i, 1, n - 1){
if (depth[edge[i].fi] > depth[edge[i].se]) swap(edge[i].fi, edge[i].se);
}
opt = BinaryIndexedTree(n + 1);
FOR(i, 1, n){
eraseEdge(i);
ans[i] = 1;
}
FOR(i, 1, m){
int u;
cin >> u;
updateEdge(u);
}
FOR(i, 1, q){
int u;
cin >> u;
cout << ans[root(u)] << endl;
}
}
/**
Warning:
Đọc sai đề???
Cận lmao
Code imple thiếu case nào không.
Limit.
**/
Compilation message (stderr)
synchronization.cpp: In member function 'void BinaryIndexedTree::update(long long int, long long int)':
synchronization.cpp:57:27: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
57 | for(int i = id; i < BIT.size(); i += i & (-i)){
| ~~^~~~~~~~~~~~
synchronization.cpp: At global scope:
synchronization.cpp:140:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
140 | main()
| ^~~~
synchronization.cpp: In function 'int main()':
synchronization.cpp:144:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
144 | freopen(TASKNAME".inp","r",stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
synchronization.cpp:145:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
145 | freopen(TASKNAME".out","w",stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |