POJ 3162 bit区间查询最值+树形DP

POJ 3162

『题目链接』POJ 3162

『题目类型』bit区间查询最值+树形DP

✡Problem:

一棵n个节点的树。wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?

✡Answer:

参考:http://blog.csdn.net/angon823/article/details/52314522
这题和HDU 2196有相同的部分,先求一下树上每个点到其它点的最远距离。问题就转化为:求一个最长的符合要求的区间,即区间里 最大值 - 最小值 < M。
我用的是树状数组初始化和查询最值,当然也可以用线段树;可以求区间最值了,那么我们用尺取法就可以求出最长的区间了:维护两个指针i,j;让i=j=1;先右移j,直到不符合情况时再右移i,之后每次更新最大长度就好了。

fread输入挂能省1s

我看了看数据,1e6,就想弄弄输入挂试试,结果如下,上面的是输入挂。fread真的牛逼,但一定不要忘了要在main函数中加2句:fread(Buf, 1, BUF, stdin); fwrite(Out, 1, ou - Out, stdout);
如果不加第一句,输入时就会rt;如果不加第二句,就没有输出。

『时间复杂度』(O(nlogn))

✡Code:

#include <map>
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <set>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define cle(a,v) memset(a,(v),sizeof(a))
#define fo(i,a,b) for(int i=(a);i<=(b);i++)
#define fd(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
const int maxn = 1e6 + 7;
int n, m, u, v, w, tot, head[maxn], dp[maxn][3], num[maxn];
struct Edge {
	int v, w, next;
} edges[maxn << 1];
void added(int u, int v, int w) {
	edges[tot] = Edge{v, w, head[u]};
	head[u] = tot++;
}
void init() {
	tot = 0;
	cle(head, -1);
}

void dfsson(int u, int fa) {
	for (int i = head[u]; ~i; i = edges[i].next) {
		int v = edges[i].v;
		if (v == fa) continue;
		dfsson(v, u);
		int temporary = dp[v][0] + edges[i].w;
		if (temporary >= dp[u][0]) {
			dp[u][1] = dp[u][0];
			dp[u][0] = temporary;
		}
		else if (temporary > dp[u][1]) {
			dp[u][1] = temporary;
		}
	}
}

void dfsfa(int u, int fa) {
	for (int i = head[u]; ~i; i = edges[i].next) {
		int v = edges[i].v;
		if (v == fa) continue;
		if (dp[u][0] == dp[v][0] + edges[i].w) {
			dp[v][2] = max(dp[u][2], dp[u][1]) + edges[i].w;
		}
		else {
			dp[v][2] = max(dp[u][2], dp[u][0]) + edges[i].w;
		}
		dfsfa(v, u);
	}
}

#define lowb(x) (x&-x)
struct node {
	int ma, mi;
} bit[maxn];
void Binit() {
	for (int i = 1; i <= n; i++) {
		bit[i].ma = num[i];
		bit[i].mi = num[i];
		for (int j = 1; j < lowb(i); j <<= 1) {
			bit[i].ma = max(bit[i].ma, bit[i - j].ma);
			bit[i].mi = min(bit[i].mi, bit[i - j].mi);
		}
	}
}
node Bquery(int l, int r) {
	node ans = node{num[r], num[r]};
	while (true) {
		ans.ma = max(ans.ma, num[r]);
		ans.mi = min(ans.mi, num[r]);
		if (r == l) break;
		for (r--; r - l >= lowb(r); r -= lowb(r)) {
			ans.ma = max(ans.ma, bit[r].ma);
			ans.mi = min(ans.mi, bit[r].mi);
		}
	}
	return ans;
}

int main() {
	freopen("1.in", "r", stdin);
	init();
	scanf("%d%d", &n, &m);
	for (int i = 2; i <= n; i++) {
		scanf("%d%d", &v, &w);
		added(i, v, w); added(v, i, w);
	}
	dfsson(1, -1);
	dfsfa(1, -1);
	for (int i = 1; i <= n; i++)
		num[i] = max(dp[i][0], dp[i][2]);
	// fo(i, 1, n) {
	// 	printf("%d ", num[i]);
	// } printf("
");
	Binit();
	int len = 1, i = 1, j = 1;
	while (j <= n) {
		node a = Bquery(i, j);
		while (a.ma - a.mi < m && j <= n) {
			j++;
			a = Bquery(i, j);
		}
		len = max(len, j - i);
		i++;
	}
	printf("%d
", len);
	return 0;
}

✡Code_fread():

#include <map>
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <set>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define cle(a,v) memset(a,(v),sizeof(a))
#define fo(i,a,b) for(int i=(a);i<=(b);i++)
#define fd(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
const int maxn = 1e6 + 7;
int n, m, u, v, w, tot, head[maxn], dp[maxn][3], num[maxn];
struct Edge {
	int v, w, next;
} edges[maxn << 1];
void added(int u, int v, int w) {
	edges[tot] = Edge{v, w, head[u]};
	head[u] = tot++;
}
void init() {
	tot = 0;
	cle(head, -1);
}

void dfsson(int u, int fa) {
	for (int i = head[u]; ~i; i = edges[i].next) {
		int v = edges[i].v;
		if (v == fa) continue;
		dfsson(v, u);
		int temporary = dp[v][0] + edges[i].w;
		if (temporary >= dp[u][0]) {
			dp[u][1] = dp[u][0];
			dp[u][0] = temporary;
		}
		else if (temporary > dp[u][1]) {
			dp[u][1] = temporary;
		}
	}
}

void dfsfa(int u, int fa) {
	for (int i = head[u]; ~i; i = edges[i].next) {
		int v = edges[i].v;
		if (v == fa) continue;
		if (dp[u][0] == dp[v][0] + edges[i].w) {
			dp[v][2] = max(dp[u][2], dp[u][1]) + edges[i].w;
		}
		else {
			dp[v][2] = max(dp[u][2], dp[u][0]) + edges[i].w;
		}
		dfsfa(v, u);
	}
}

#define lowb(x) (x&-x)
struct node {
	int ma, mi;
} bit[maxn];
void Binit() {
	for (int i = 1; i <= n; i++) {
		bit[i].ma = num[i];
		bit[i].mi = num[i];
		for (int j = 1; j < lowb(i); j <<= 1) {
			bit[i].ma = max(bit[i].ma, bit[i - j].ma);
			bit[i].mi = min(bit[i].mi, bit[i - j].mi);
		}
	}
}
node Bquery(int l, int r) {
	node ans = node{num[r], num[r]};
	while (true) {
		ans.ma = max(ans.ma, num[r]);
		ans.mi = min(ans.mi, num[r]);
		if (r == l) break;
		for (r--; r - l >= lowb(r); r -= lowb(r)) {
			ans.ma = max(ans.ma, bit[r].ma);
			ans.mi = min(ans.mi, bit[r].mi);
		}
	}
	return ans;
}


const int BUF = 40000000;
char Buf[BUF], *buf = Buf;
const int OUT = 20000000;
char Out[OUT], *ou = Out; int Outn[30], Outcnt;
inline void write(int x) {
	if (!x)*ou++ = 48;
	else {
		for (Outcnt = 0; x; x /= 10)Outn[++Outcnt] = x % 10 + 48;
		while (Outcnt)*ou++ = Outn[Outcnt--];
	}
}
inline void writell(ll x) {
	if (!x)*ou++ = 48;
	else {
		for (Outcnt = 0; x; x /= 10)Outn[++Outcnt] = x % 10 + 48;
		while (Outcnt)*ou++ = Outn[Outcnt--];
	}
}
inline void writechar(char x) {*ou++ = x;}
inline void writeln() {*ou++ = '
';}
inline void read(int&a) {for (a = 0; *buf < 48; buf++); while (*buf > 47)a = a * 10 + *buf++ -48;}


int main() {
	freopen("1.in", "r", stdin);
	init();
	//DON'T FOGET THIS!!!
	fread(Buf, 1, BUF, stdin);
	read(n), read(m);
	for (int i = 2; i <= n; i++) {
		read(v), read(w);
		added(i, v, w); added(v, i, w);
	}
	dfsson(1, -1);
	dfsfa(1, -1);
	for (int i = 1; i <= n; i++)
		num[i] = max(dp[i][0], dp[i][2]);
	// fo(i, 1, n) {
	// 	printf("%d ", num[i]);
	// } printf("
");
	Binit();
	int len = 1, i = 1, j = 1;
	while (j <= n) {
		node a = Bquery(i, j);
		while (a.ma - a.mi < m && j <= n) {
			j++;
			a = Bquery(i, j);
		}
		len = max(len, j - i);
		i++;
	}
	write(len);
	writeln();
	//DON'T FOGET THIS!!!
	fwrite(Out, 1, ou - Out, stdout);
	return 0;
}

原文地址:https://www.cnblogs.com/s1124yy/p/7305555.html