제출 #106046

#제출 시각아이디문제언어결과실행 시간메모리
106046AngusRitossaUnique Cities (JOI19_ho_t5)C++14
64 / 100
1829 ms247160 KiB
#include <bits/stdc++.h>
using namespace std;
#ifdef DEBUG
	#define D(x...) printf(x)
#else
	#define D(x...)
#endif
vector<int> adj[200010];
vector<int> indonother[200010];
int n, val[200010], m;

int rangetreeleft[17500010];
int rangetreeright[17500010];
int rangetreeval[17500010];
int upto;
void setto1(int node, int curr, int oldcurr, int cstart = 0, int cend = 200010)
{
	if (cstart == cend)
	{
		rangetreeval[curr] = 1;
		return;
	}
	int mid = (cstart+cend)/2;
	if (node <= mid)
	{
		rangetreeleft[curr] = ++upto;
		rangetreeright[curr] = rangetreeright[oldcurr];
		setto1(node, rangetreeleft[curr], rangetreeleft[oldcurr], cstart, mid);
	}
	else
	{
		rangetreeright[curr] = ++upto;
		rangetreeleft[curr] = rangetreeleft[oldcurr];
		setto1(node, rangetreeright[curr], rangetreeright[oldcurr], mid+1, cend);
	}
	rangetreeval[curr] = max(0, rangetreeval[rangetreeleft[curr]]) + max(0, rangetreeval[rangetreeright[curr]]);
}
void setto0(int s, int e, int curr, int oldcurr, int cstart = 0, int cend = 200010)
{
	// also, conveniently, sets e+1 to 1
	rangetreeval[curr] = rangetreeval[oldcurr];
	if (s <= cstart && cend <= e)
	{
		rangetreeval[curr] = -1;
		return;
	}
	int mid = (cstart+cend)/2;
	if (e <= mid)
	{
		rangetreeleft[curr] = ++upto;
		rangetreeright[curr] = rangetreeright[oldcurr];
		setto0(s, e, rangetreeleft[curr], rangetreeleft[oldcurr], cstart, mid);
		if (e == mid)
		{
			rangetreeright[curr] = ++upto;
			setto1(e+1, rangetreeright[curr], rangetreeright[oldcurr], mid+1, cend);
		}
	}
	else if (s > mid)
	{
		rangetreeright[curr] = ++upto;
		rangetreeleft[curr] = rangetreeleft[oldcurr];
		setto0(s, e, rangetreeright[curr], rangetreeright[oldcurr], mid+1, cend);
	}
	else
	{
		rangetreeleft[curr] = ++upto;
		rangetreeright[curr] = ++upto;
		setto0(s, e, rangetreeleft[curr], rangetreeleft[oldcurr], cstart, mid);
		setto0(s, e, rangetreeright[curr], rangetreeright[oldcurr], mid+1, cend);
	}
	rangetreeval[curr] = rangetreeval[curr] == -1 ? 0 : max(0, rangetreeval[rangetreeleft[curr]]) + max(0, rangetreeval[rangetreeright[curr]]);
}
void whichonesare1(int curr, int cstart = 0, int cend = 200010)
{
	if (!rangetreeval[curr]) return;
	if (cstart == cend) D("is set to 1 %d\n", cstart);
	int mid = (cstart+cend)/2;
	whichonesare1(rangetreeleft[curr], cstart, mid);
	whichonesare1(rangetreeright[curr], mid+1, cend);
}
pair<int, int> maxdis[200010][3];
int seen[200010], leafdis[200010];
int distoleaf(int a)
{
	if (seen[a]) return leafdis[a];
	seen[a] = 1;
	for (auto b : adj[a])
	{
		if (!seen[b]) leafdis[a] = max(leafdis[a], distoleaf(b));
	}
	D("distoleaf %d - %d\n", a, leafdis[a]+1);
	return ++leafdis[a];
}
void findmxdis(int a, int par = -1, int pardis = 0)
{
	maxdis[a][0] = { pardis, (par == -1) ? adj[a].size() : par };
	maxdis[a][1].second = maxdis[a][2].second = adj[a].size();
	for (int j = 0; j < (int)adj[a].size(); j++)
	{
		int b = adj[a][j];
		if (j != par)
		{
			pair<int, int> d = { distoleaf(b), j };
			if (d > maxdis[a][0])
			{	
				maxdis[a][2] = maxdis[a][1];
				maxdis[a][1] = maxdis[a][0];
				maxdis[a][0] = d;
			}
			else if (d > maxdis[a][1])
			{
				maxdis[a][2] = maxdis[a][1];
				maxdis[a][1] = d;
			}
			else if (d > maxdis[a][2])
			{
				maxdis[a][2] = d;
			}
		}
	}
	for (int j = 0; j < (int)adj[a].size(); j++)
	{
		int b = adj[a][j];
		if (j != par)
		{
			int newpardis = 0;
			if (maxdis[a][0].second != j) newpardis = maxdis[a][0].first;
			else if (maxdis[a][1].second != j) newpardis = maxdis[a][1].first;
			newpardis++;
			findmxdis(b, indonother[a][j], newpardis);
		}
	}
	D("done... %d - %d %d %d\n", a, maxdis[a][0].second, maxdis[a][1].second, maxdis[a][2].second);
}
vector<int> ans[200010];
int saveroots[200010];
int returntree(int a, int b)
{
	if (upto >= 17490000) while (1) {}
	if (a == 0) return 0;
	if (ans[a][b]) return ans[a][b];
	D("\n%d %d - %d\n", a, b, adj[a][b]);
	int x = 0, y = 1;
	if (maxdis[a][x].second == b) x++, y++;
	else if (maxdis[a][y].second == b) y++;
	D("a %d b %d, x y %d %d - mxdisx %d\n", a, b, x, y, maxdis[a][x].second);
	D("%d - %lu\n", maxdis[a][x].second, adj[a].size());
	int root = returntree(adj[a][maxdis[a][x].second], indonother[a][maxdis[a][x].second]);
	int newroot;
	D("a %d b %d - setting %d\n", a, b, maxdis[a][x].first);
	if (maxdis[a][y].first)
	{
//		newroot = ++upto;
		D("a %d b %d - setting to 0 - %d to %d\n", a, b, maxdis[a][x].first-maxdis[a][y].first, maxdis[a][x].first-1);
	//	setto1(maxdis[a][x].first, newroot, root);
		//root = newroot;
		newroot = ++upto;
		setto0(maxdis[a][x].first-maxdis[a][y].first, maxdis[a][x].first-1, newroot, root);
	}
	else
	{
		if (root == saveroots[rangetreeval[root]])
	{
		if (saveroots[rangetreeval[root]+1]) newroot = saveroots[rangetreeval[root]+1];
		else 
		{
			newroot = saveroots[rangetreeval[root]+1] = ++upto;
			setto1(maxdis[a][x].first, newroot, root);
		}
	}
	else 
	{
		newroot = ++upto;
		setto1(maxdis[a][x].first, newroot, root);
	}
	}
	return ans[a][b] = newroot;
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i < n; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		indonother[a].push_back(adj[b].size());
		indonother[b].push_back(adj[a].size());
		adj[a].push_back(b);
		adj[b].push_back(a);
		ans[a].push_back(0);
		ans[b].push_back(0);
	}
	distoleaf(1);
	findmxdis(1);
	for (int i = 1; i <= n; i++) scanf("%d", &val[i]), adj[i].push_back(0), indonother[i].push_back(0);
	for (int i = 1; i <= n; i++)
	{
		ans[i].push_back(0);
		ans[i].push_back(0);
		adj[i].push_back(0);
		indonother[i].push_back(0);
		int root = returntree(i, adj[i].size()-1);
		printf("%d\n", max(0, min(rangetreeval[root]-1, m)));
	//	whichonesare1(root);
	}
}

컴파일 시 표준 에러 (stderr) 메시지

joi2019_ho_t5.cpp: In function 'int main()':
joi2019_ho_t5.cpp:182:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &n, &m);
  ~~~~~^~~~~~~~~~~~~~~~
joi2019_ho_t5.cpp:186:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d", &a, &b);
   ~~~~~^~~~~~~~~~~~~~~~
joi2019_ho_t5.cpp:196:72: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for (int i = 1; i <= n; i++) scanf("%d", &val[i]), adj[i].push_back(0), indonother[i].push_back(0);
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...