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("\n");
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\n", 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++ = '\n';}
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("\n");
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;
}
POJ 3162 bit区间查询最值+树形DP的更多相关文章
- NOIP2011pj表达式的值[树形DP 笛卡尔树 | 栈 表达式解析]
题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ...
- POJ 2342 &&HDU 1520 Anniversary party 树形DP 水题
一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点) ...
- 洛谷P1351 联合权值(树形dp)
题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...
- 洛谷 P1351 联合权值 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...
- POJ - 2057 The Lost House(树形DP+贪心)
https://vjudge.net/problem/POJ-2057 题意 有一只蜗牛爬上某个树枝末睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面,.现在这只蜗牛要求寻找 ...
- poj 2342 【Anniversary party】树形dp
题目传送门//res tp poj 题意 给出一棵有权树,求一个节点集的权值和,满足集合内的任意两点不存在边 分析 每个点有选中与不选中两种状态,对于第\(i\)个点,记选中为\(sel_i\),不选 ...
- POJ 1849 Two(树的直径--树形DP)(好题)
大致题意:在某个点派出两个点去遍历全部的边,花费为边的权值,求最少的花费 思路:这题关键好在这个模型和最长路模型之间的转换.能够转换得到,全部边遍历了两遍的总花费减去最长路的花费就是本题的答案,要思考 ...
- poj 1694 An Old Stone Game 树形dp
//poj 1694 //sep9 #include <iostream> #include <algorithm> using namespace std; const in ...
- POJ题目1947 Rebuilding Roads(树形dp)
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9957 Accepted: 4537 ...
随机推荐
- Python面向对象之魔术方法
__str__ 改变对象的字符串显示.可以理解为使用print函数打印一个对象时,会自动调用对象的__str__方法 class Student: def __init__(self, name, a ...
- 取消layUI中日期选择控件默认填充日期
input标签中使用日期选择控件填写,加载时默认填充当前日期, 标签设置了placeholder="请选择" autocomplete="off",但是并没有效 ...
- Python中的作用域及global用法
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的. 函数定义了本地作用域,而模块定义的是全局作用域. 如果想要在函数内定义全局作用域,需要加上global修饰符. 变量名解析:LE ...
- Python基础——切片实例
切片实例 L = list(range(100)) print(L, end=' ') [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1 ...
- css 制作圆角、圆形图形布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D
目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...
- Laravel项目部署上线(阿里云 Ubuntu 16.04)
第一次尝试把本地的项目上线, 购买了某云的轻量应用服务器, 镜像为Ubuntu 16.04 直接运行 apt-get install nginx 出错 根据提示运行 apt-get upda ...
- Web Driver 8中定位方法 ——基于python语言
WebDriver提供了八种元素定位方法,在python 语言中,方法如下: id定位:find_element_by_id("id值"):id属性是唯一的. 1 driver ...
- llinux挂载多个光驱
因为u盘量产,一个u盘两启,所以linux需要访问多个cdrom(一个物理光驱,一个虚拟光驱),本来一位无法使用,看了看/dev目录下面, [root@linux-node3 cdrom]$ ll / ...
- C#基础概念总结
C#基础概念总结 1..NET Framework概念 2. C#的含义: 3.什么是面向对象编程: 4.Visual Studio开发工具: 5..NET程序运行的机制: 1..Net Framew ...