[NOIP 2018 Day1] 简要题解
[题目链接]
铺设道路 : https://www.luogu.org/problemnew/show/P5019
货币系统 : https://www.luogu.org/problemnew/show/P5020
赛道修建 :https://www.luogu.org/problemnew/show/P5021
[题解]
Problem A 铺设道路
首先 , 我们有一个分治的思路 , 对于一段区间[l , r] , 最优策略为将区间内的所有数都减掉区间中的最小值 , 然后将该问题分成两个子问题 , 分治下去即可 , 时间复杂度 : O(N ^ 2)
用ST表预处理区间最小值 , 分治时实现O(1)查询 , 时间复杂度优化为 O(NlogN)
我们还可以使用贪心算法 , 如果第i个数 > 第(i - 1)个数 , 则它们对答案产生了(Hi - Hi-1)的“贡献” , 贡献相加即为答案 , 证明略 , 时间复杂度 : O(N)
Problem B 货币系统
首先有一个结论 : 在最优的情况下 , 必然满足m为n的子集 , 这个结论是显然的
根据这个结论 , 我们不妨将a数组按升序排序 , 若第(k + 1)个数能由前k个数组合出 , 则删除第(k + 1)个数
具体实现时可以完全背包 , 时间复杂度 : O(TNW)(取W = 25000)
Problem C 赛道修建
要求长度最小的赛道长度尽可能大 , 我们不妨二分答案limit
对于以u为根节点的一棵子树 , 我们可以记录每一条连接到u的赛道的长度value , 和这条路径的长度u ,若 :
1. value + w >= limit , 将答案加一 , 单独构成一条赛道
2. value + w < limit , 对于这种情况 , 我们将(value + w)插入到一棵平衡树(可以方便使用std :: multimap)
然后 , 对于平衡树中的每个数w , 我们贪心地将找到最小的v , 使得w + v >= limit , 并在平衡树中删除w和v
最后我们只要判断路径条数是否 >= m , 即可
时间复杂度 : O(NlogN ^ 2) , 注意优化常数 , 如二分上界可定为树的直径
[代码]
铺设道路 :
// Sprease Table O(NlogN)
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
const int MAXLOG = ; int n;
long long ans;
int a[MAXN];
int mn[MAXN][MAXLOG] , loc[MAXN][MAXLOG]; template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline pair<int , int> query(int l , int r)
{
int k = (int)((double)log(r - l + ) / log(2.0));
int ret1 = min(mn[l][k] , mn[r - ( << k) + ][k]);
int ret2;
if (mn[l][k] < mn[r - ( << k) + ][k]) ret2 = loc[l][k];
else ret2 = loc[r - ( << k) + ][k];
return make_pair(ret1 , ret2);
}
inline void solve(int l , int r , int k)
{
if (l > r) return;
pair<int , int> tmp = query(l , r);
ans += tmp.first - k;
solve(l , tmp.second - , tmp.first);
solve(tmp.second + , r , tmp.first);
} int main()
{ read(n);
for (int i = ; i <= n; i++)
{
read(a[i]);
mn[i][] = a[i];
loc[i][] = i;
}
for (int j = ; j < MAXLOG; j++)
{
for (int i = ; i + ( << j) - <= n; i++)
{
mn[i][j] = min(mn[i][j - ] , mn[i + ( << (j - ))][j - ]);
if (mn[i][j - ] < mn[i + ( << (j - ))][j - ]) loc[i][j] = loc[i][j - ];
else loc[i][j] = loc[i + ( << (j - ))][j - ];
}
}
solve( , n , );
cout<< ans << "\n"; return ;
}
货币系统 :
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110 int n;
int a[MAXN];
bool dp[]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
int main()
{ int T;
read(T);
while (T--)
{
read(n);
for (int i = ; i <= n; i++) read(a[i]);
memset(dp , false , sizeof(dp));
dp[] = true;
int ans = ;
sort(a + , a + n + );
for (int i = ; i <= n; i++)
{
if (dp[a[i]]) continue;
++ans;
for (int j = a[i]; j <= ; j++)
{
dp[j] |= dp[j - a[i]];
}
}
printf("%d\n" , ans);
} return ; }
赛道修建 :
#include<bits/stdc++.h>
using namespace std;
#define MAXN 50010
typedef long long ll;
typedef long double ld;
const ll inf = 1e15; struct edge
{
int to , w , nxt;
} e[MAXN << ]; int n , m , tot , cnt;
int head[MAXN];
ll dist[MAXN];
multiset< ll > M[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline void addedge(int u , int v , int w)
{
++tot;
e[tot] = (edge){v , w , head[u]};
head[u] = tot;
}
inline ll dfs(int u , int father , ll limit)
{
M[u].clear();
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to , w = e[i].w;
if (v == father) continue;
ll val = dfs(v , u , limit) + (ll)w;
if (val >= limit) ++cnt;
else M[u].insert(val);
}
ll ret = ;
while (!M[u].empty())
{
if ((int)M[u].size() == )
{
chkmax(ret , *M[u].begin());
break;
} else
{
ll tmp = *M[u].begin();
M[u].erase(M[u].begin());
multiset< ll > :: iterator it = M[u].lower_bound(limit - tmp);
if (it == M[u].end())
{
chkmax(ret , tmp);
} else
{
++cnt;
M[u].erase(it);
}
}
}
return ret;
}
inline ll diameter()
{
queue< int > q;
for (int i = ; i <= n; i++) dist[i] = inf;
dist[] = ;
q.push();
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to , w = e[i].w;
if (dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
q.push(v);
}
}
}
int s = ;
for (int i = ; i <= n; i++)
if (dist[i] > dist[s]) s = i;
for (int i = ; i <= n; i++) dist[i] = inf;
dist[s] = ;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to , w = e[i].w;
if (dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
q.push(v);
}
}
}
ll ret = ;
for (int i = ; i <= n; i++) chkmax(ret , dist[i]);
return ret;
}
inline bool check(ll mid)
{
cnt = ;
dfs( , , mid);
return cnt >= m;
} int main()
{ read(n); read(m);
ll l = , r = , ans = ;
for (int i = ; i < n; i++)
{
int u , v , w;
read(u); read(v); read(w);
addedge(u , v , w);
addedge(v , u , w);
}
r = diameter();
while (l <= r)
{
ll mid = (l + r) >> ;
if (check(mid))
{
ans = mid;
l = mid + ;
} else r = mid - ;
}
printf("%lld\n" , ans); return ; }
[NOIP 2018 Day1] 简要题解的更多相关文章
- A · F · O —— JLOI2018翻车记(附Day1简要题解)
JLOI2018翻车记 并不知道该怎么写... 算了还是按照标准剧情来吧 这应该是一篇写得非常差的流水账... 2018.04.04 Day -1 省选前在机房的最后一天. 压力并不是很大,毕竟联赛 ...
- NOIP 2018 day1 题解
今年noip的题和去年绝对是比较坑的题了,但是打好的话就算是普通水准也能350分以上吧. t1: 很显然这是一个简单的dp即可. #include<iostream> #include&l ...
- NOIP 2018 Day1
Fei2Xue@Lian$Tian! 三道原题qwq真的凉 半年前看到有人发说说,梦见省选打开题目,是Please contact lydsy2012@163.com! 没想到一语成谶 大众分300 ...
- JLOI2015 DAY1 简要题解
「JLOI2015」有意义的字符串 题意 给你 \(b, d, n\) 求 \[ [(\frac{b + \sqrt d}2)^n] \mod 7528443412579576937 \] \(0 & ...
- SCOI2016 Day1 简要题解
目录 「SCOI2016」背单词 题意 题解 代码 「SCOI2016」幸运数字 题意 题解 总结 代码 「SCOI2016」萌萌哒 题意 题解 总结 代码 「SCOI2016」背单词 题意 这出题人 ...
- SCOI 2015 Day1 简要题解
「SCOI2015」小凸玩矩阵 题意 一个 \(N \times M\)( $ N \leq M $ )的矩阵 $ A $,要求小凸从其中选出 $ N $ 个数,其中任意两个数字不能在同一行或同一列, ...
- AHOI2013 Round2 Day1 简要题解
第一题,好吧这是个dp.(搜素也能在BZOJ上卡过). 第二题,BFS搜索碰到的立方体面数,智硬没有想到... 第三题,其实一看就有思路,但关键是求x坐标不交的矩形对数+y坐标不交的矩形对数 - x, ...
- noip 2018 day1 T2 货币系统 完全背包
Code: #include<cstdio> #include<string> #include<cstring> #include<algorithm> ...
- noip 2018 day1 T3 赛道修建 贪心_树上问题_multiset
Code: // luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; #define maxn 5000 ...
随机推荐
- Influx kafka
http://www.opscoder.info/kafka-influxdb.html
- .NET Core 3.0之创建基于Consul的Configuration扩展组件
写在前面 经过前面三篇关于.NET Core Configuration的文章之后,本篇文章主要讨论如何扩展一个Configuration组件出来.如果前面三篇文章没有看到,可以点击如下地址访问 .N ...
- 从Activity的启动流程理解Binder
简述 关于Activity启动流程和Binder的文章很多,大多数是分开来讲的,本文将二者结合起来,着重分析启动流程中跨进程方面的细节,其实,启动流程看似调用繁多,主要是复杂在Activity栈管理等 ...
- 一起来学Spring Cloud | 第五章:熔断器 ( Hystrix)
在微服务项目中,一个系统可以分割成很多个不同的服务模块,不同模块之间我们通常需要进行相互调用.springcloud中可以使用RestTemplate+Ribbon和Feign来调用(工作中基本都是使 ...
- vue之组件注册
一.组件名 写组件之前你要明确你的目的,想要做一个什么样的组件,我们在注册一个组件的时候,需要给组件一个名字,对于命名,尽可能明确,使用 kebab-case (短横线分隔命名) 或 PascalCa ...
- chmod u g x o 777
chmod [ugoa] [+-= ] [rwx] 文件或者是目录u:表示文件的属主,g:表文件的属组内的成员,o:则表示其它用户,a:是所有用户的(ugo的总和)+—=:是对权限的操作,+表示增加相 ...
- 【LeetCode】Generate Parentheses 解题报告
[题目] Given n pairs of parentheses, write a function to generate all combinations of well-formed pare ...
- react 使用 moment 进行 日期格式化
在react中使用得先导入: import moment from 'moment'; 调用: npm install moment var moment = require('moment'); m ...
- Cg入门8:Vertex Shader - 更好的数据组织方式struct
数据结构的使用:与C语言语法一样 參数的传递:參数匹配的是映射的语义的类型 输入输出:採用结构体,输入输出相应的參数的in和out可省略.函数的參数结构体就是输入參数集,函数的返回结构体就是输出參数集 ...
- Android Problem- android.content.res.Resources$NotFoundException: String resource ID #0xa
在使用listview时出现错误android.content.res.Resources$NotFoundException: String resource ID #0xa 经查证是在调用Text ...