Submission #972910

#TimeUsernameProblemLanguageResultExecution timeMemory
972910dio_2Synchronization (JOI13_synchronization)C++17
100 / 100
295 ms30700 KiB
#include<bits/stdc++.h>
using namespace std;

struct FenwickTree{
    vector<long long> fenw;
    int n;
    
    FenwickTree () {}
    
    FenwickTree (int siz){
		init(siz);
	}
    
    void init(int siz){
        n = siz;
        fenw.assign(n, 0);
    }
    \
    long long sum(int r){
        long long res = 0;
        while(r >= 0){
            res += fenw[r];
            r = (r & (r + 1)) - 1;
        }
        return res;
    }
    
    long long sum(int l, int r){
        long long res = sum(r);
        if(l) res -= sum(l - 1);
        return res;
    }
    
    void add(int where, long long val){
        while(where < n){
            fenw[where] += val;
            where |= (where + 1);
        }
    }
    
    void set(int where, long long val){
        long long cr = sum(where, where);
        add(where, -cr + val);
    }
};

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n, m, q;
	cin >> n >> m >> q;
	
	vector<vector<int>> g(n + 1);
	vector<pair<int, int>> kraw(n);
	vector<int> state_kraw(n); // na poczatky wszytko jest off.
	
	for(int i = 0;i < n - 1;i++){
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
		kraw[i + 1] = make_pair(a, b);
	}
	
	vector<int> dep(n + 1), tin(n + 1), tout(n + 1);
	vector<int> parent(n + 1), parent_kraw(n + 1);
	vector<int> passed_cnt(n + 1); // ile przeszlo od danej krawedzi
	vector<int> info(n + 1, 1); // ile informacij ma dane korzenie ( czyli leader DSU )
	
	const int LOG = 20;
	vector<vector<int>> up(n + 1, vector<int> (LOG, 1));
	FenwickTree fen(2 * n + 2); 
	// 1) query me to root it is (1, in[u])
	// 2) update my weight is +w on in[u], -w on out[u]. :)

	int T = 1;
	auto dfs1 = [&](auto &&dfs1, int u, int p)->void{
		tin[u] = T++;
		for(int v : g[u]) if(v != p){
			parent[v] = u;
			dep[v] = dep[u] + 1;
			up[v][0] = u;
			for(int i = 1;i < LOG;i++) up[v][i] = up[ up[v][i - 1] ][i - 1];
			dfs1(dfs1, v, u);
		}
		tout[u] = T++;
	}; dfs1(dfs1, 1, 0);
	
	auto lca = [&](int a, int b)->int{
		assert(a != b); // its just that i won't be doing such queries
		if(dep[a] > dep[b]) swap(a, b);
		int diff = dep[b] - dep[a];
		for(int i = LOG - 1;i >= 0;i--){
			if((diff >> i) & 1){
				b = up[b][i];
			}
		}
		assert(dep[b] == dep[a]);
		if(a == b) return a;
		for(int i = LOG - 1;i >= 0;i--){
			if(up[a][i] != up[b][i]){
				a = up[a][i];
				b = up[b][i];
			}
		}
		return up[a][0];
	};
	
	for(int i = 1;i <= n - 1;i++){
		auto [a, b] = kraw[i];
		if(dep[a] > dep[b]) swap(a, b);
		parent_kraw[b] = i;
	}
	
	auto isAnc = [&](int a, int b)->bool{
		return tin[a] <= tin[b] and tout[b] <= tout[a];
	};
	
	auto isOnPath = [&](int a, int b)->int{
		if(dep[a] > dep[b]) swap(a, b);
		assert(isAnc(a, b));
		int dA = fen.sum(1, tin[a]);
		int dB = fen.sum(1, tin[b]);
		return dep[b] - dep[a] == dB - dA;
	};
	
	auto go_up = [&](int &a)->void{
		for(int j = LOG - 1;j >= 0;j--){
			if(isOnPath(a, up[a][j])){
				a = up[a][j];
			}
		}
	};
	
	while(m--){
		int e;
		cin >> e;
		
		auto [a, b] = kraw[e];
		if(dep[a] > dep[b]) swap(a, b);
		// a na gorze
		
		if(!state_kraw[e]){ // polacz 
			// b jest korzeniem dolnego poddrzewa
			// dla a nie wiemy kim jest leaderem treba isc do gory do poki mozna
			//~ while(parent[a] and state_kraw[ parent_kraw[a] ] ) a = parent[a]; // this is the SLOW.
			fen.set(tin[b], 1);
			fen.set(tout[b], -1); // you update deeper.
			go_up(a);
			int przejdzie = info[b] - passed_cnt[e];
			info[a] += przejdzie;
			passed_cnt[e] += przejdzie;
		} else { // rozlacz
			//~ while(parent[a] and state_kraw[ parent_kraw[a] ] ) a = parent[a]; // SLOW 
			go_up(a);
			fen.set(tin[b], 0);
			fen.set(tout[b], 0);
			passed_cnt[e] = info[a];
			info[b] = info[a];
		}
		
		state_kraw[e] ^= 1;
	}
	
	for(int i = 0;i < q;i++){
		int a;
		cin >> a;
		//~ while(parent[a] and state_kraw[ parent_kraw[a] ] ) a = parent[a]; // SLOW  
		go_up(a);
		cout << info[a] << '\n';                              
	}
	
	return 0;	
}

Compilation message (stderr)

synchronization.cpp: In function 'int main()':
synchronization.cpp:90:7: warning: variable 'lca' set but not used [-Wunused-but-set-variable]
   90 |  auto lca = [&](int a, int b)->int{
      |       ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...