嘟嘟嘟




因为一些知道的人所知道的,不知道的人所不知道的原因,我来改写今年的NOIP了。

现在看这题,心中满是疑问:我当时是多么的zz,这种水题为啥没做出来……




不管了,说正事。

先考虑部分分。

1.\(n \leqslant 15\)

不会。

2.\(m = 1\)

带权树的直径啊。树形dp一下维护最长链次长链即可。

3.菊花图。

最长的一组路径显然可能是由一条边或是任意两条边组成。

当\(m <= \frac{n - 1}{2}\)的时候,贪心把前\(2m\)大的边最大的匹配最小的即可。

否则把最大的一些单独拎出来,剩下的两两匹配就完事了。

答案就是所有的max。

然后我考场上把这个写跪了……原因是第一种情况直接最大的匹配最小的,那中间的给扔了。(怒丢20分)

4.链

普及二分题。




这就是大众分55分啦。




至于二叉树咋回事,可以说是标程的弱化版。

也是二分,然后判断能否选出大于等于mid的m条路来。

然后对于每一个结点,分情况讨论:

1.如果左子树的链加边权大于等于mid,断掉作为一条新赛道。

2.右子树同理。

3.如果其中一棵子树的链加上边权比mid小,就贪心的把更长的链接到这个节点上,用来往上延伸。

没啦。




那么标程就很显然了。

对于结点\(u\),能在子树内匹配的就在子树内匹配,否则找一条最长的链延伸上去。

实现的时候每一层用一个multiset或vector+sort都行。




然后luogu卡vector(loj上过了),非得换成multiset。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<set>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 5e4 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, m;
struct Edge
{
int nxt, to, w;
}e[maxn << 1];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y, int w)
{
e[++ecnt] = (Edge){head[x], y, w};
head[x] = ecnt;
} int a[maxn];
In void work0() //菊花图
{
--n;
for(int i = 0, j = 1; i <= ecnt; i += 2, ++j) a[j] = e[i].w;
sort(a + 1, a + n + 1);
if(m <= (n >> 1))
{
int L = n - (m << 1) + 1;
int Min = INF;
for(int i = L, j = 1; j <= m; ++i, ++j) Min = min(Min, a[i] + a[n - j + 1]);
write(Min), enter;
}
else
{
int tp = n - m, Min = INF;
for(int i = 1; i <= tp; ++i) Min = min(Min, a[i] + a[(tp << 1) - i + 1]);
Min = min(Min, a[(tp << 1) + 1]);
write(Min), enter;
}
} In void dfs1(int now, int _f, int stp)
{
for(int i = head[now], v; i != -1; i = e[i].nxt)
if((v = e[i].to) ^ _f) a[stp] = e[i].w, dfs1(v, now, stp + 1);
}
In bool judge1(ll x)
{
int cnt = 0;
for(int i = 1, sum = 0; i < n; ++i)
{
if(sum + a[i] >= x) ++cnt, sum = 0;
else sum += a[i];
}
return cnt >= m;
}
In void work1() //链
{
dfs1(1, 0, 1);
ll L = 0, R = (ll)5e9;
while(L < R)
{
ll mid = (L + R) >> 1;
if(judge1(mid))
{
if(L == mid) break;
L = mid;
}
else
{
if(R == mid - 1) break;
R = mid - 1;
}
}
write(L), enter;
} ll dp[maxn], ans = 0;
In void dfs2(int now, int _f)
{
ll Max1 = 0, Max2 = 0;
for(int i = head[now], v; i != -1; i = e[i].nxt)
{
if((v = e[i].to) == _f) continue;
dfs2(v, now);
if(dp[v] + e[i].w > Max1) Max2 = Max1, Max1 = dp[v] + e[i].w;
else if(dp[v] + e[i].w > Max2) Max2 = dp[v] + e[i].w;
}
ans = max(ans, Max1 + Max2);
dp[now] = Max1;
} In void work2() //m = 1
{
dfs2(1, 0);
write(ans), enter;
} int cnt = 0;
multiset<ll>::iterator pos; multiset<ll> val[maxn];
In void dfs(int now, int _f, ll x)
{
for(int i = head[now], v; i != -1; i = e[i].nxt)
{
if((v = e[i].to) == _f) continue;
dfs(v, now, x);
dp[v] += e[i].w;
if(dp[v] >= x) ++cnt;
else val[now].insert(dp[v]);
}
ll Max = 0;
while(!val[now].empty())
{
if(val[now].size() == 1) {Max = max(Max, *val[now].begin()); val[now].erase(val[now].find(*val[now].begin())); break;}
pos = val[now].lower_bound(x - *val[now].begin());
if(pos == val[now].end())
{
Max = max(Max, *val[now].begin());
val[now].erase(val[now].find(*val[now].begin()));
}
else
{
++cnt;
val[now].erase(val[now].find(*pos));
val[now].erase(val[now].find(*val[now].begin())); }
}
dp[now] = Max;
}
In bool judge(ll x)
{
cnt = 0;
dfs(1, 0, x);
return cnt >= m;
} int main()
{
Mem(head, -1);
n = read(), m = read();
bool flg0 = 1, flg1 = 1;
ll sum = 0;
for(int i = 1; i < n; ++i)
{
int x = read(), y = read(), w = read();
addEdge(x, y, w); addEdge(y, x, w);
if(x ^ 1) flg0 = 0;
if(y != x + 1) flg1 = 0;
sum += w;
}
if(flg0) {work0(); return 0;}
if(flg1) {work1(); return 0;}
if(m == 1) {work2(); return 0;}
ll L = 0, R = sum;
while(L < R)
{
ll mid = (L + R + 1) >> 1;
if(judge(mid)) L = mid;
else R = mid - 1;
}
write(L), enter;
return 0;
}

[NOIP2018]赛道修建的更多相关文章

  1. Luogu5021 [NOIP2018]赛道修建

    Luogu5021 [NOIP2018]赛道修建 一棵大小为 \(n\) 的树,边带权.选 \(m\) 条链使得长度和最小的链最大. \(m<n\leq5\times10^4\) 贪心,二分答案 ...

  2. 【LG5021】[NOIP2018]赛道修建

    [LG5021][NOIP2018]赛道修建 题面 洛谷 题解 NOIP之前做过增强版还没做出来\(QAQ\) 一看到题目中的最大值最小,就很容易想到二分答案 重点是考虑如何\(check\) 设\( ...

  3. 竞赛题解 - NOIP2018 赛道修建

    \(\mathcal {NOIP2018}\) 赛道修建 - 竞赛题解 额--考试的时候大概猜到正解,但是时间不够了,不敢写,就写了骗分QwQ 现在把坑填好了~ 题目 (Copy from 洛谷) 题 ...

  4. [NOIP2018]赛道修建(二分+multiset)

    考场上打了一个 \(vector\) 解法,因为我当时不会 \(multiset\) 好吧,我来讲一讲今年的 \(tgD1T3\) 首先,这题 \(55\) 分是不难想的 1. \(b_i=a_i+1 ...

  5. 【比赛】NOIP2018 赛道修建

    最小值最大,二分长度 然后判断赛道大于等于这个长度最多可以有多少条 可以贪心,对于一个点和它的一些儿子,儿子与儿子之间尽量多配(排序后一大一小),剩下的选个最长的留给自己的父亲就好了 具体实现可以用一 ...

  6. luogu5021 [NOIp2018]赛道修建 (二分答案+dp(贪心?))

    首先二分一下答案,就变成了找长度>=m的 不相交的路径的个数 考虑到在一个子树中,只有一个点能出这个子树去和别的点搞 所以我这个子树里尽量自我满足是不会有坏处的 而且要在自我满足数最大的条件下, ...

  7. 【题解】NOIP2018 赛道修建

    题目戳我 \(\text{Solution:}\) 根据题目信息简化题意,是让你在树上找出\(m\)条路径使得路径长度最小值最大. 看到题第一感先二分一个答案,问题转化为如何选择一些路径使得它们最小值 ...

  8. [NOIp2018提高组]赛道修建

    [NOIp2018提高组]赛道修建 题目大意: 给你一棵\(n(n\le5\times10^4)\)个结点的树,从中找出\(m\)个没有公共边的路径,使得第\(m\)长的路径最长.问第\(m\)长的路 ...

  9. noip2018 D1T3 赛道修建

    题目描述 C 城将要举办一系列的赛车比赛.在比赛前,需要在城内修建 mm 条赛道. C 城一共有 nn 个路口,这些路口编号为 1,2,…,n1,2,…,n,有 n-1n−1 条适合于修建赛道的双向通 ...

随机推荐

  1. Java设计模式学习记录-迭代器模式

    前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...

  2. [Luogu 3787] 冰精冻西瓜

    Description 琪露诺是拥有操纵冷气程度的能力的妖精,一天她发现了一片西瓜地.这里有n个西瓜,由n-1条西瓜蔓连接,形成一个有根树,琪露诺想要把它们冷冻起来慢慢吃. 这些西瓜蔓具有神奇的性质, ...

  3. httpd配置文件httpd.conf规则说明和一些基本指令

    apache httpd系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html 本文主要介绍的是httpd的配置文件,包括一些最基本的指令.配置规 ...

  4. ASP .NET MVC HtmlHelper扩展——简化“列表控件”的绑定

    在众多表单元素中,有一类<select>元素用于绑定一组预定义列表.传统的ASP.NET Web Form中,它对应着一组重要的控件类型,即ListControl,我们经常用到DropDo ...

  5. Receiver 和 Direct方式的区别

    Kafka direct 跟receiver 方式接收数据的区别? Receiver是使用Kafka的高层次Consumer API来实现的.Receiver从Kafka中获取的数据都是存储在Spar ...

  6. Java学习笔记之——变量与数据类型、运算符

    一.变量 1.变量:变化的值 变量在代码运行期间,开辟了一块空间 .这块空间是有地址的,给这块取了个名字, 这个名字就叫做变量名,这块空间放的东西叫做变量值 2.变量的初始化: (1)先声明再赋值: ...

  7. elasticsearch6.7 01.入门指南(2)

    2.安装(略) 默认情况下,elasticsearch 使用端口 9200 来访问它的 REST API.如果有必要,该端口也可以配置 3.探索集群 3.1 The REST API 既然我们已经启动 ...

  8. 【读书笔记】iOS-对iOS应用进行模糊测试

    一,模糊测试,是指通过反复向待测应用发送畸形的数据,对应用进行动态测试的过程. 二,模糊测试,也称动态分析,是一种构造非法输入并将其提供给应用,以期让应用暴露出某些安全问题的艺术和科学. 参考资料:& ...

  9. Java数据解析---PULL

    安卓和JAVA解析xml文件的三种方式: 1.PULL解析 2.SAX解析 3.DOM解析 三者各有所长,依情况选择解析方式 1.PULL和SAX均采用流式解析,意味着只能从头读到底,无法像DOM解析 ...

  10. 安卓开发之自定义一个view弹出框

    https://www.cnblogs.com/muyuge/p/6152167.html