[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 ...
随机推荐
- js Math [ 随机数、绝对值、四舍五入、进一取整、舍去取整、最大值、最小值、圆周率 ]
<script> /* 数学对象:Math */ with (document) { write('<br>-3.5的绝对值:'+Math.abs(-3.5)); write( ...
- (8)C#连sqlserver
str="Data Source=ip; Network Library=DBMSSOCN; Initial Catalog=数据库; User ID=sa; Password=xx&quo ...
- Callable和Runnable和FutureTask
http://www.cnblogs.com/dolphin0520/p/3949310.html 一.Callable与Runnable 二.Future 三.FutureTask 四.使用示例 一 ...
- Heavy Transportation(最短路)
poj 1797 ——Heavy Transportation 思路: 这道题我们可以采用类似于求最短路径的方法,用一种新的“松弛操作”去取代原本的方法. 我们可以记录d[u]为运送货物到点j时最大可 ...
- delphi函数大全
delphi函数大全Abort 函数 引起放弃的意外处理Abs 函数 绝对值函数AddExitProc ...
- 转:Python yield 使用浅析 from IBM Developer
评注:没有看懂. 转: https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ Python yield 使用浅析 初 ...
- PAT 1003 Sharing (25)
题目描写叙述 To store English words, one method is to use linked lists and store a word letter by letter. ...
- [unity3d]unity平台的预处理
在开发中,特别是unity的跨平台中,我们常常会在各个平台游走,如安卓版,苹果版,PC版.......在此不同的平台上,有可能我们须要做不同的操作.然而我们就能够用unity的自带的平台宏定义方式来做 ...
- C# Backgroundworker(后台线程)的使用
namespace BackgroundWorkderPauseSample { public partial class MainForm : Form { BackgroundWorker wor ...
- Android studio 百度地图开发(2)地图定位
Android studio 百度地图开发(2)地图定位 email:chentravelling@163.com 开发环境:win7 64位,Android Studio,请注意是Android S ...