zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    顺序查找
    折半查找
    KMP
    php长时间的脚本,报502
    AcWing 27. 数值的整数次方
    acwing 25. 剪绳子
    Best Cow Line <挑战程序设计竞赛> 习题 poj 3617
    acwing 23. 矩阵中的路径
    AcWing 34. 链表中环的入口结点
    AcWing 33. 链表中倒数第k个节点
  • 原文地址:https://www.cnblogs.com/s1124yy/p/7305555.html
Copyright © 2011-2022 走看看