牛客NOIP暑期七天营-提高组1 解题报告
https://ac.nowcoder.com/acm/contest/920#question
A
构造+双指针
发现m的限制是1e5,而点数是5e4,所以不能构造太多的边,思考一下最短路树的定义。会发现其实就是要构造出一个最短路树。按\(a_i\)升序排序,那么只需要找一个在\(a_i-S\)的点连边即可。这个玩意可以直接用双指针或者二分或者其他什么数据结构来实现。判断无解即判断是否存在大于S的边或者0边。复杂度\(O(n \log n)\)
#include <bits/stdc++.h>
using namespace std;
namespace io {
char buf[1<<21], *p1 = buf, *p2 = buf;
inline char gc() {
if(p1 != p2) return *p1++;
p1 = buf;
p2 = p1 + fread(buf, 1, 1 << 21, stdin);
return p1 == p2 ? EOF : *p1++;
}
#define G gc
#ifndef ONLINE_JUDGE
#undef G
#define G getchar
#endif
template<class I>
inline void read(I &x) {
x = 0; I f = 1; char c = G();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = G(); }
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = G(); }
x *= f;
}
template<class I>
inline void write(I x) {
if(x == 0) {putchar('0'); return;}
I tmp = x > 0 ? x : -x;
if(x < 0) putchar('-');
int cnt = 0;
while(tmp > 0) {
buf[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while(cnt > 0) putchar(buf[--cnt]);
}
#define in(x) read(x)
#define outn(x) write(x), putchar('\n')
#define out(x) write(x), putchar(' ')
} using namespace io;
#define ll long long
const int N = 100010;
int n, S, m;
struct Node {int v, id;} a[N];
struct edge {int u, v, w;} e[N];
bool operator < (Node a, Node b) {
return a.v < b.v;
}
int main() {
read(n); read(S);
for(int i = 1; i <= n; ++i) read(a[i].v), a[i].id = i;
sort(a + 1, a + n + 1);
bool flag = 0; int last = 1;
for(int i = 2; i <= n; ++i) {
if(a[i].v == 0) {flag = 1; break;}
while(last < i && a[i].v - a[last].v > S) ++last;
e[++m] = {a[last].id, a[i].id, a[i].v - a[last].v};
}
for(int i = 1; i <= m; ++i) if(e[i].w > S || e[i].w < 1) flag = 1;
if(flag) puts("-1");
else {
printf("%d\n", m);
for(int i = 1; i <= m; ++i) printf("%d %d %d\n", e[i].u, e[i].v, e[i].w);
}
return 0;
}
B
构造+贪心+01trie
因为是一个完全图,所以题目等价于,1到n的排列中,相邻两个数作为下标,\(a_i\)的\(xor\)最大值最小是多少。
因为高位对答案的影响更大,按位考虑,我们肯定需要让当前位为1的排在一块,为0的排在一块,那么答案的最大值一定在中间接壤点(因为这两部分内部再怎么xor也没这一位的一个1贡献大)。
所以找出有0也有1的最高位,然后将序列划分为两段。那么问题就变成了,在序列0和序列1中各选出一个数,使他们的xor和尽可能小。这个01Trie维护一下就好了。
赛时是写了一个同样思想的归并排序,但是没有想到“这两部分内部再怎么xor也没这一位的一个1贡献大”这一性质,所以写挂了...
#include <bits/stdc++.h>
using namespace std;
namespace io {
char buf[1<<21], *p1 = buf, *p2 = buf;
inline char gc() {
if(p1 != p2) return *p1++;
p1 = buf;
p2 = p1 + fread(buf, 1, 1 << 21, stdin);
return p1 == p2 ? EOF : *p1++;
}
#define G gc
#ifndef ONLINE_JUDGE
#undef G
#define G getchar
#endif
template<class I>
inline void read(I &x) {
x = 0; I f = 1; char c = G();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = G(); }
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = G(); }
x *= f;
}
template<class I>
inline void write(I x) {
if(x == 0) {putchar('0'); return;}
I tmp = x > 0 ? x : -x;
if(x < 0) putchar('-');
int cnt = 0;
while(tmp > 0) {
buf[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while(cnt > 0) putchar(buf[--cnt]);
}
#define in(x) read(x)
#define outn(x) write(x), putchar('\n')
#define out(x) write(x), putchar(' ')
} using namespace io;
#define ll long long
const int N = 1000100;
int n, t[N * 10][2], tot;
ll a[N], b[N][2];
void insert(ll x) {
int u = 0;
for(ll pos = 60; pos >= 0; --pos) {
int c = (x >> pos) & 1LL;
if(!t[u][c]) t[u][c] = ++tot;
u = t[u][c];
}
}
ll query(ll x) {
int u = 0; ll ans = 0;
for(ll pos = 60; pos >= 0; --pos) {
int c = (x >> pos) & 1LL;
if(t[u][c]) u = t[u][c];
else u = t[u][c ^ 1], ans += 1LL << pos;
}
return ans;
}
int main() {
read(n);
for(int i = 1; i <= n; ++i) read(a[i]);
int cnt[2];
for(ll pos = 60; pos >= 0; --pos) {
cnt[0] = cnt[1] = 0;
for(int i = 1; i <= n; ++i) {
int c = (a[i] >> pos) & 1;
b[++cnt[c]][c] = a[i];
}
if(cnt[0] && cnt[1]) break;
}
if(!cnt[0] || !cnt[1]) return puts("0"), 0;
for(int i = 1; i <= cnt[0]; ++i) insert(b[i][0]);
ll ans = 1LL << 61;
for(int i = 1; i <= cnt[1]; ++i) ans = min(ans, query(b[i][1]));
outn(ans);
}
C
最短路树+spfa
同起点到两个点的最短路的公共部分等价于该起点的最短路树上这两个点的lca到根的距离。字典序最小的话建最短路树的时候处理一下就好。将询问离线下来,每次处理出当前起点下的最短路树,然后对每个询问依次取max。这样就只用开一个最短路树的空间了。复杂度是O(nqlogn + nmk)(k为spfa中的那个常数)。正解是在建最短路树那里用Johnson算法,卡了spfa。因为过于码农所以没补这题= =记录了一下思想。
然后johnson算法的话,就是定义一个虚点,然后到每个点连长度为0的边,然后spfa一次跑出最短路,然后这个最短路就是每个节点的势能函数,记为h。那么将边权改为h[v]-h[u]+w,就能保证不存在负边权了,于是跑DIjkstra,最后将势能函数反推回去就可以得到最短路了。
这个玩意好像在rqy的Dijkstra跑费用流的课件里面看到过。
牛客NOIP暑期七天营-提高组1 解题报告的更多相关文章
- 牛客NOIP暑期七天营-普及组1 解题报告
A 对于\(100\%\),直接开个桶统计即可.入门题目. 代码:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41 ...
- 牛客NOIP暑期七天营-提高组1
牛客NOIP暑期七天营-提高组1 链接 A 边权可为0就排序建一条链子. 但是边权不为0 除了第一个有0的不行. x连向上一个比他小的数. 期间判断有无解. #include <bits/std ...
- 牛客NOIP暑期七天营-提高组6
目录 A-积木大赛 题目描述 link 题解 代码 B-破碎的序列 题目描述 link 题解 C-分班问题 题目描述 link 题解 比赛链接 官方题解 A-积木大赛 题目描述 link 题解 标签: ...
- 牛客NOIP暑期七天营-提高组5+普及组5
————提高组———— 第一题:deco的abs 题目链接:https://ac.nowcoder.com/acm/contest/934/A 因为每个数都可以加任意次 d ,所以可以推出 0 < ...
- 牛客NOIP暑期七天营-提高组3
第一题:破碎的矩阵 题目链接:https://ac.nowcoder.com/acm/contest/932/A 刚看到这题的时候感觉特别熟悉...诶,这不就是codeforces某场比赛的某某 ...
- 牛客NOIP暑期七天营-提高组2
第一题:ACGT 题目链接:https://ac.nowcoder.com/acm/contest/931/A trie树.hash.map遍历 ①.trie树上的节点多记一个rest值表示还有多少 ...
- 牛客NOIP暑期七天营-提高组6C:分班问题 (组合数)
题意:A班有N个人,B班有M个人,现在要组成一个新的班级C班,为了公平,从AB班各抽相同人数的人. 现在求所有方案中,人数之和是多少. 思路:即求Σ k*C(N,k)*C(M,k); 先忽略这个 ...
- 牛客NOIP暑期七天营-提高组5
A:deco的abs. 水题,先%,然后相邻两个数min()一下差值. #include<bits/stdc++.h> #define ll long long using namespa ...
- 牛客NOIP暑期七天营-提高组2C:滑块(平衡树) (这里rope骗分)
A:hash 或者 map 或者trie. #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) usin ...
随机推荐
- IntellJ idea maven打包——项目带有第三方jar包
今天用maven打包时,提示程序包com.aspose.slides不存在 原来第三方jar是直接导入的,打包时没找到 那项目中带有第三方jar包,怎么打包? 方法: 1.根路径建立lib包,将第三方 ...
- 【VS开发】Visual C++内存泄露检测—VLD工具使用说明
Visual C++内存泄露检测-VLD工具使用说明 一. VLD工具概述 Visual Leak Detector(VLD)是一款用于Visual C++的免费的内存泄露检测工具.他的 ...
- java开发异常Exception集锦
背景:整理开发过程中的异常问题 java.lang.Exception: No tests found matching 一般出现在新导入的工程中.在sts中通过open project的方式导入工程 ...
- Lambda的延迟执行
在兼顾面向对象特性的基础上,Java语言通过Lambda表达式与方法引用等,为开发者打开了函数式编程的大门. 下面我们做一个初探. Lambda的延迟执行 有些场景的代码执行后,结果不一定会被使用,从 ...
- python的安装与配置
pyhton的下载与安装 1.python官网地址:https://www.python.org 2.下载 Python 编辑器PyCharm PyCharm 是一款功能强大的 Python 编辑器 ...
- c++中的不是数的数nan
matlab中经常碰到nan,inf等特殊“数”,而在C++中也有相应的表示:例如std::numeric_limits <float>::quiet_NaN ();可以得到浮点型的nan ...
- python 之 Django框架(服务器程序和应用程序、基础必备三件套及相关配置)
第十二章 Django框架 12.1 服务器程序和应用程序 服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理.应用程序则负责具体的逻辑处理.为了方便应用程序的开发, ...
- python学习-63 组合
组合 1.什么是组合? 定义一个类,由数据属性构成,这几个属性又可以是通过一个类实例化的对象,这就是组合. 举例: class School: def __init__(self,name,addre ...
- 登陆并访问k8s的apiserver
kubeadm安装的k8s集群默认需要用户登陆认证,无法直接使用命令curl访问.所以首先的第一步就是获取token. 先找到k8s集群中的dns组件coredns,之前的版本使用的是kube-dns ...
- H5新特性 本地存储---cookie localStorage sessionStorage
本地存储的作用 :避免登录网站时,用户在页面浏览时重复登录,也可以实现快速登录,一段时间内保存用户的登录效果,提高页面访问速率 在html5中提供三种数据持久化操作的方法: 1.cookie 可看作是 ...