Submission #1036525

#TimeUsernameProblemLanguageResultExecution timeMemory
1036525model_codePetrol stations (CEOI24_stations)C++17
100 / 100
1486 ms1759084 KiB
// Author: Jiří Kalvoda
#include<bits/stdc++.h>

using namespace std;

using ll = long long;

int n;
ll k;

struct Treap
{
	Treap *left=0, *right=0;
	ll key;
	int priority;
	int count;
	int subtree_count;
	int subtree_size;
	Treap * clone();
	Treap * calc()
	{
		subtree_count = count;
		if (left) subtree_count += left->subtree_count;
		if (right) subtree_count += right->subtree_count;

		subtree_size = 1;
		if (left) subtree_size += left->subtree_size;
		if (right) subtree_size += right->subtree_size;
		return this;
	}
	Treap * init(ll key_, int count_)
	{
		this->priority = random();
		this->key = key_;
		this->count = count_;
		calc();
		return this;
	}
};
Treap * treap_aloc;
int treap_aloc_count;
Treap *new_treap()
{
	if(!treap_aloc_count)
	{
		treap_aloc_count = 1000;
		treap_aloc = new Treap[treap_aloc_count];
	}
	treap_aloc_count--;
	return treap_aloc++;
}
Treap * Treap::clone()
{
	Treap * t = new_treap();
	t->left = left;
	t->right = right;
	t->key = key;
	t->count = count;
	t->priority = priority;
	t->calc();
	return t;
}

int max_h = 0;
Treap *merge(Treap *left, Treap *right, int h=0)
{
	max_h = max(max_h, h);
	if (!left || !right) return left?left:right;
	if (left->priority < right->priority)
	{
		left = left->clone();
		left->right = merge(left->right, right, h+1);
		return left->calc();
	}
	else
	{
		right = right->clone();
		right->left = merge(left, right->left, h+1);
		return right->calc();
	}
}

pair<Treap*, Treap*> split(Treap *in, ll key, int h=0)
{
	max_h = max(max_h, h);
	if (!in) return {NULL, NULL};
	in = in->clone();
	Treap *left=in,*right=in;
	if (in->key <  key)
		tie(left->right, right) = split(in->right, key, h+1);
	else
		tie(left, right->left) = split(in->left, key, h+1);
	if(left) left = left->calc();
	if(right) right = right->calc();
	return {left, right};
}

void printttr(FILE * out, Treap *tr, ll key_shift)
{
	if(!tr) return;
	fprintf(out, "{");
	printttr(out, tr->left, key_shift);
	fprintf(out, "[%d %d %d]", tr->key+key_shift, tr->count, tr->subtree_count);
	printttr(out, tr->right, key_shift);
	fprintf(out, "}");
}

struct DataStr {
	Treap * tr=NULL;
	ll key_shift=0;
	int del_negative()
	{
		Treap *to_remove;
		tie(to_remove, tr) = split(tr, 0-key_shift);
		return to_remove?to_remove->subtree_count:0;
	}
	void add(ll key, int count)
	{
		if(!count) return;
		Treap *a, *b, *c;
		tie(a,b) = split(tr, key-key_shift);
		tie(b,c) = split(b, key-key_shift+1);
		if(b)
		{
			b = b->clone();
			b->count += count;
			b->calc();
		}
		else
			 b = new_treap()->init(key-key_shift, count);
		tr = merge(a, merge(b,c));
	}
	void add_from(Treap * from, ll from_key_shift, int multiple=1)
	{
		if(!from) return;
		add(from->key + from_key_shift, from->count * multiple);
		add_from(from->left, from_key_shift, multiple);
		add_from(from->right, from_key_shift, multiple);
	}
};

DataStr merge_ds(DataStr a, DataStr b)
{
	if(!a.tr) return b;
	if(!b.tr) return a;
	if(a.tr->subtree_size > b.tr->subtree_size)
		return merge_ds(b, a);
	b.add_from(a.tr, a.key_shift);
	return b;
}

struct Node{
	vector<pair<Node*, ll>> e;
	pair<Node*, ll> up;
	ll counts=0;
	int id;
	int subtree_size;
	DataStr dp_here;
	DataStr dp_after_edge;
	int make_rooted(Node * _up)
	{
		subtree_size=1;
		for(int i=0; i<e.size(); i++)
		{
			if(e[i].first == _up)
			{
				up = e[i];
				e[i] = e[e.size()-1];
				e.pop_back();
			}
		}
		for(auto &[nd, l] : e)
			subtree_size += nd->make_rooted(this);
		sort(e.begin(), e.end(), [](auto &a, auto &b){return a.first->subtree_size > b.first->subtree_size;});
		return subtree_size;
	}
	void go()
	{
		dp_here.add(k, 1);
		for(auto &[nd, l] : e)
			nd->go();
		for(auto &[nd, l] : e)
			dp_here = merge_ds(nd->dp_after_edge, dp_here);
		dp_after_edge = dp_here;
		dp_after_edge.key_shift -= up.second;
		ll c = dp_after_edge.del_negative();
		counts += c*(n-subtree_size);
		dp_after_edge.add(k-up.second, c);
		// printf("GO %d %d\n", id, c);
		// printttr(stdout, dp_after_edge.tr, dp_after_edge.key_shift);
		// printf("\n");
	}
	void go2(vector<DataStr> dp_down)
	{
		bool first = true;
		for(auto &[nd, l] : e)
		{
			vector<DataStr> dp_down_nd = dp_down;
			assert(1<<dp_down_nd.size() <= n);
			if(first)
			{
				first=false;
				dp_down_nd[0].add(k, 1);

				for(auto &[nd2, l2] : e) if(nd2 != nd)
					dp_down_nd[0] = merge_ds(dp_down_nd[0], nd2->dp_after_edge);
				}
			else
			{

				DataStr tmp = dp_here;
				tmp.add_from(nd->dp_after_edge.tr, nd->dp_after_edge.key_shift, -1);
				dp_down_nd.push_back(tmp);
			}

			ll c = 0;
			for(auto &it: dp_down_nd)
			{
				it.key_shift -= l;
				c += it.del_negative();
			}
			counts += c*nd->subtree_size;
			dp_down_nd[0].add(k-l, c);

			nd->go2(dp_down_nd);
		}
	}
} *nds;

int main(int argc, char ** argv)
{
	srand(42);
	scanf("%d%lld", &n, &k);
	nds = new Node[n];
	for (int i=0; i<n; i++) nds[i].id = i;
	for (int i=0; i<n-1; i++)
	{
		int a,b;
		ll l;
		scanf("%d%d%lld", &a, &b, &l);
		nds[a].e.push_back({nds+b, l});
		nds[b].e.push_back({nds+a, l});
	}
	nds[0].make_rooted(NULL);
	nds[0].go();
	nds[0].go2({DataStr()});
	for (int i=0; i<n; i++) printf("%lld\n", nds[i].counts);
	fprintf(stderr, "max treap height: %d\n", max_h);
	return 0;
}

Compilation message (stderr)

Main.cpp: In function 'void printttr(FILE*, Treap*, ll)':
Main.cpp:103:18: warning: format '%d' expects argument of type 'int', but argument 3 has type 'll' {aka 'long long int'} [-Wformat=]
  103 |  fprintf(out, "[%d %d %d]", tr->key+key_shift, tr->count, tr->subtree_count);
      |                 ~^          ~~~~~~~~~~~~~~~~~
      |                  |                 |
      |                  int               ll {aka long long int}
      |                 %lld
Main.cpp: In member function 'int Node::make_rooted(Node*)':
Main.cpp:163:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<Node*, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  163 |   for(int i=0; i<e.size(); i++)
      |                ~^~~~~~~~~
Main.cpp: In function 'int main(int, char**)':
Main.cpp:233:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  233 |  scanf("%d%lld", &n, &k);
      |  ~~~~~^~~~~~~~~~~~~~~~~~
Main.cpp:240:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  240 |   scanf("%d%d%lld", &a, &b, &l);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...