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的更多相关文章

  1. NOIP2011pj表达式的值[树形DP 笛卡尔树 | 栈 表达式解析]

    题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ...

  2. POJ 2342 &&HDU 1520 Anniversary party 树形DP 水题

    一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点) ...

  3. 洛谷P1351 联合权值(树形dp)

    题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...

  4. 洛谷 P1351 联合权值 —— 树形DP

    题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...

  5. POJ - 2057 The Lost House(树形DP+贪心)

    https://vjudge.net/problem/POJ-2057 题意 有一只蜗牛爬上某个树枝末睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面,.现在这只蜗牛要求寻找 ...

  6. poj 2342 【Anniversary party】树形dp

    题目传送门//res tp poj 题意 给出一棵有权树,求一个节点集的权值和,满足集合内的任意两点不存在边 分析 每个点有选中与不选中两种状态,对于第\(i\)个点,记选中为\(sel_i\),不选 ...

  7. POJ 1849 Two(树的直径--树形DP)(好题)

    大致题意:在某个点派出两个点去遍历全部的边,花费为边的权值,求最少的花费 思路:这题关键好在这个模型和最长路模型之间的转换.能够转换得到,全部边遍历了两遍的总花费减去最长路的花费就是本题的答案,要思考 ...

  8. poj 1694 An Old Stone Game 树形dp

    //poj 1694 //sep9 #include <iostream> #include <algorithm> using namespace std; const in ...

  9. POJ题目1947 Rebuilding Roads(树形dp)

    Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9957   Accepted: 4537 ...

随机推荐

  1. 前后台得到WEB应用的名称

    前台得到当前应用的名称: ${ pageContext.request.contextPath } 后台得到当前应用的名称: request.getServletContext().getContex ...

  2. linux抓包工具tcpdump使用总结

    tcpdump采用命令行方式对接口的数据包进行筛选抓取,其丰富特性表现在灵活的表达式上 1.格式 # tcpdump --help tcpdump version 4.1-PRE-CVS_2012_0 ...

  3. python统计字词练习

    方法一: import operator from nltk.corpus import stopwords stop_words = stopwords.words('English')#目的是去除 ...

  4. 作用域和闭包(二)this

    this 要在执行时才确认,定义时无法确认 1. 作为构造函数执行 2. 作为对象属性执行 3.作为普通函数执行 4. call,apply,bind 改变this

  5. java判断通常的逻辑

    package com.stylefeng.guns.core.common.constant.factory; import com.baomidou.mybatisplus.mapper.Enti ...

  6. HTML5_canvas_线性渐变

    canvas 线性渐变 var linearG = pen.createLinearGradient(startX, startY, endX, endY); 两点的连线,决定了渐变的方向,和区间 v ...

  7. 8. 环境变量_数据库_mongoose的基本使用_模型对象的CRUD

    1. 环境变量 系统环境(cmd)使用的变量/命令 能够让我们在cmd环境下运行指定的程序 用户环境变量 path(我们一般设置这个) 系统环境变量 path 过程: 当我们在cmd中输入一个指令 先 ...

  8. MYSQL定时任务 触发器

    流程: 查看时间调度器是否开启,OFF关闭,ON开启 SHOW VARIABLES LIKE 'event_scheduler' 设置开启 set GLOBAL event_scheduler = 1 ...

  9. django分页

    page_count = 1 current_page = int(request.GET.get('p',1)) course1 = Course.objects.all().order_by('- ...

  10. JVM内存模型与垃圾回收

    内存模型 1,程序计数器(Program Counter Register):程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器.字节码解 ...