Submission #256425

#TimeUsernameProblemLanguageResultExecution timeMemory
256425IvanCConstruction of Highway (JOI18_construction)C++17
100 / 100
406 ms85868 KiB
#include <bits/stdc++.h>
#define LSOne(S) (S&(-S))
using namespace std;

typedef tuple<int,int,int> trinca;
typedef pair<int,int> ii;

const int MAXN = 1e5 + 10;

vector<int> grafo[MAXN];
vector<int> compressao;
vector<ii> quantities;
deque<trinca> componente[MAXN];
int pai[MAXN], szTree[MAXN], color[MAXN], aresta1[MAXN], aresta2[MAXN], N;
int chainId[MAXN], posChain[MAXN], headChain[MAXN], chainPtr, lastChain;
int fenwickTree[MAXN];

inline void upd_bit(int pos, int delta){
	while(pos < MAXN){
		fenwickTree[pos] += delta;
		pos += LSOne(pos);
	}
}

inline int read(int pos){
	int ans = 0;
	while(pos > 0){
		ans += fenwickTree[pos];
		pos -= LSOne(pos);
	}
	return ans;
}

int query(int pos){
	return read(MAXN-1) - read(pos);
}

void dfs1(int v, int p){

	szTree[v] = 1;
	pai[v] = p;

	for(int u: grafo[v]){
		if(u == p) continue;
		dfs1(u, v);
		szTree[v] += szTree[u];
	}

}

void dfs2(int v, int p){

	int mx = -1, big = -1;
	if(chainId[v] == 0){
		chainId[v] = ++lastChain;
		headChain[chainId[v]] = v;
		posChain[v] = ++chainPtr;
	}

	componente[chainId[v]].push_back(make_tuple(color[v], posChain[v], posChain[v]));

	for(int u: grafo[v]){
		if(u == p) continue;
		if(szTree[u] > mx){
			mx = szTree[u];
			big = u;
		}
	}

	if(big != -1){
		chainId[big] = chainId[v];
		posChain[big] = ++chainPtr;
		dfs2(big, v);
	}

	for(int u: grafo[v]){
		if(u == p || u == big) continue;
		dfs2(u, v);
	}

}

long long query_up(int v){

	//printf("#######\nQuery %d\n", v);
	vector<ii> pares;
	int new_color = color[v];
	v = pai[v];
	long long ans = 0;

	while(v != -1){

		int thisChain = chainId[v];
		int thisHead = headChain[thisChain];
		int lo = posChain[thisHead];
		int hi = posChain[v];

		//printf("V %d tC %d tH %d (%d, %d)\n", v, thisChain, thisHead, lo, hi);

		while(!componente[thisChain].empty()){
			//printf("Loop\n");
			trinca davez = componente[thisChain].front();
			if(get<1>(davez) > hi){
				break;
			}
			else if(get<2>(davez) <= hi){
				int whichColor = get<0>(davez);
				int whichSize = get<2>(davez) - get<1>(davez) + 1;
				componente[thisChain].pop_front();
				quantities.push_back(ii(whichColor, whichSize));
			}
			else{
				int whichColor = get<0>(davez);
				int oldBegin = get<1>(davez);
				int oldEnd = get<2>(davez);
				componente[thisChain].pop_front();
				componente[thisChain].push_front(make_tuple(whichColor, hi + 1, oldEnd));
				int whichSize = hi - oldBegin + 1;
				quantities.push_back(ii(whichColor, whichSize));
			}
		}

		while(!quantities.empty()){
			if(!pares.empty() && pares.back().first == quantities.back().first){
				pares.back().second += quantities.back().second;
			}
			else{
				pares.push_back(quantities.back());
			}
			quantities.pop_back();
		}

		componente[thisChain].push_front(make_tuple(new_color, lo, hi));

		v = pai[thisHead];

	} 

	reverse(pares.begin(), pares.end());
	/*
	for(int i = 0; i < pares.size(); i++){
		printf("(%d, %d)", pares[i].first, pares[i].second);
	}
	printf("\n");
	printf("#######\n");*/

	for(int i = 0; i < pares.size(); i++){
		int thisColor = pares[i].first;
		int thisQuantity = pares[i].second;
		ans += 1LL*thisQuantity*query(thisColor);
		upd_bit(thisColor, thisQuantity);
	}

	for(int i = 0; i < pares.size(); i++){
		int thisColor = pares[i].first;
		int thisQuantity = pares[i].second;
		upd_bit(thisColor, -thisQuantity);
	}

	return ans;

}

int main(){

	scanf("%d", &N);

	for(int i = 1; i <= N; i++){
		scanf("%d", &color[i]);
		compressao.push_back(color[i]);
	}
	sort(compressao.begin(), compressao.end());
	for(int i = 1; i <= N; i++){
		color[i] = lower_bound(compressao.begin(), compressao.end(), color[i]) - compressao.begin() + 1;
	}

	for(int i = 1; i < N; i++){
		scanf("%d %d", &aresta1[i], &aresta2[i]);
		grafo[aresta1[i]].push_back(aresta2[i]);
	}

	dfs1(1, -1);
	dfs2(1, -1);

	for(int i = 1; i < N; i++){

		int v = aresta2[i];
		long long ans = query_up(v);
		printf("%lld\n", ans);

	}

	return 0;

}

Compilation message (stderr)

construction.cpp: In function 'long long int query_up(int)':
construction.cpp:147:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i = 0; i < pares.size(); i++){
                 ~~^~~~~~~~~~~~~~
construction.cpp:154:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i = 0; i < pares.size(); i++){
                 ~~^~~~~~~~~~~~~~
construction.cpp: In function 'int main()':
construction.cpp:166:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d", &N);
  ~~~~~^~~~~~~~~~
construction.cpp:169:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d", &color[i]);
   ~~~~~^~~~~~~~~~~~~~~~~
construction.cpp:178:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d %d", &aresta1[i], &aresta2[i]);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...