程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Bzoj 1803 spoj qtree3 主席樹

Bzoj 1803 spoj qtree3 主席樹

編輯:C++入門知識

靠又別水題虐了。。。


題目還是比較基礎的

就是直接樹上k大就可以了

首先一次dfs得到dfs序

然後建立主席樹


接下來詢問的時候

因為dfs序每個節點出現過兩次

所以k大的k要乘2

然後直接兩個線段樹減一下就可以了


總體來說還是挺簡單的。。。


但是我還是進了主席樹的大坑

就是空間問題。。。

調了好久才剛剛不MLE了。。。大家注意啊。。

#include 
#include 
#include 
#include 
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define MAX 200009
#define u 18

using namespace std;

int to[1 * MAX], next[1 * MAX], head[1 * MAX], a[MAX], c[MAX];
int n, m, k, dfn[MAX * 1], tree[u * MAX], child[u * MAX][2], size[u * MAX];
int tot = 0, DfsClock = 0, sum = 0, first[MAX * 1], last[1 * MAX], num = 0;

inline void add (int x, int y)
{
	to[++tot] = y;
	next[tot] = head[x];
	head[x] = tot;
}

void dfs (int x, int fa)
{
	dfn[first[x] = ++DfsClock] = x;
	for (int i = head[x]; i; i = next[i])
		if (to[i] != fa)
			dfs (to[i], x);
	dfn[last[x] = ++DfsClock] = x;
}

inline int add (int l, int r, int pos, int root)
{
	int New = ++sum, mid = (l + r) >> 1;
	size[New] = size[root] + 1;
	if (l == r)
		return New;
	if (pos <= mid)
		child[New][0] = add (l, mid, pos, child[root][0]), child[New][1] = child[root][1];
	else
		child[New][0] = child[root][0], child[New][1] = add (mid + 1, r, pos, child[root][1]);
	return New;
}

struct wbysr
{
	int value, id;
}e[MAX];

bool cmp (wbysr a1, wbysr a2)
{
	return a1.value < a2.value;
}

int main()
{
	scanf ("%d", &n);
	rep (i, 1, n)
		scanf ("%d", &a[i]), e[i].value = a[i], e[i].id = i;
	sort (e + 1, e + 1 + n, cmp);
	e[0].value = e[1].value - 90;
	rep (i, 1, n)
		if (e[i].value != e[i-1].value)
			c[++num] = e[i].value;
	rep (i, 1, n - 1)
	{
		int a1, a2;
		scanf ("%d%d", &a1, &a2);
		add (a1, a2);
		add (a2, a1);
	}
	dfs (1,0);
	tree[0] = 0;
	size[0] = 0;
	rep (i, 1, DfsClock)
		tree[i] = add (1, num, lower_bound (c + 1, c + 1 + num, a[dfn[i]]) - c, tree[i - 1]);


	scanf ("%d", &m);
	while (m--)
	{
		int x;
		scanf ("%d%d", &x, &k);
		k *= 2;
		int t0 = tree[first[x] - 1], t1 = tree[last[x]];
		int l = 1, r = num;
		while (l <= r)
		{
			int now = size[child[t1][0]] - size[child[t0][0]];
			int mid = (l + r) >> 1;
			if (k <= now)
				t0 = child[t0][0], t1 = child[t1][0], r = mid;
			else
				t0 = child[t0][1], t1 = child[t1][1], k -= now, l = mid + 1;
		}
		printf ("%d\n", e[r].id);
	}
	return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved