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 解题报告的更多相关文章

  1. 牛客NOIP暑期七天营-普及组1 解题报告

    A 对于\(100\%\),直接开个桶统计即可.入门题目. 代码:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41 ...

  2. 牛客NOIP暑期七天营-提高组1

    牛客NOIP暑期七天营-提高组1 链接 A 边权可为0就排序建一条链子. 但是边权不为0 除了第一个有0的不行. x连向上一个比他小的数. 期间判断有无解. #include <bits/std ...

  3. 牛客NOIP暑期七天营-提高组6

    目录 A-积木大赛 题目描述 link 题解 代码 B-破碎的序列 题目描述 link 题解 C-分班问题 题目描述 link 题解 比赛链接 官方题解 A-积木大赛 题目描述 link 题解 标签: ...

  4. 牛客NOIP暑期七天营-提高组5+普及组5

    ————提高组———— 第一题:deco的abs 题目链接:https://ac.nowcoder.com/acm/contest/934/A 因为每个数都可以加任意次 d ,所以可以推出 0 < ...

  5. 牛客NOIP暑期七天营-提高组3

    第一题:破碎的矩阵 题目链接:https://ac.nowcoder.com/acm/contest/932/A    刚看到这题的时候感觉特别熟悉...诶,这不就是codeforces某场比赛的某某 ...

  6. 牛客NOIP暑期七天营-提高组2

    第一题:ACGT 题目链接:https://ac.nowcoder.com/acm/contest/931/A trie树.hash.map遍历  ①.trie树上的节点多记一个rest值表示还有多少 ...

  7. 牛客NOIP暑期七天营-提高组6C:分班问题 (组合数)

    题意:A班有N个人,B班有M个人,现在要组成一个新的班级C班,为了公平,从AB班各抽相同人数的人. 现在求所有方案中,人数之和是多少. 思路:即求Σ k*C(N,k)*C(M,k);    先忽略这个 ...

  8. 牛客NOIP暑期七天营-提高组5

    A:deco的abs. 水题,先%,然后相邻两个数min()一下差值. #include<bits/stdc++.h> #define ll long long using namespa ...

  9. 牛客NOIP暑期七天营-提高组2C:滑块(平衡树) (这里rope骗分)

    A:hash 或者 map 或者trie. #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) usin ...

随机推荐

  1. Java设计模式之:单例模式

    单例模式 建议实现方式:枚举方式实现单例 单例模式的定义 单例模式就是在程序运行中只实例化一次,创建一个全局唯一对象,有点像 Java 的静态变量,但是单例模式要优于静态变量,静态变量在程序启动的时候 ...

  2. java内存泄露/溢出等常见问题模拟及原因分析

    Java 8:从持久代到metaspace 系统稳定性--OutOfMemoryError 常见原因及解决方法 java各种异常问题示例(附pdf下载): java.lang.OutOfMemoryE ...

  3. H5混合开发中android终端和ios终端常见的兼容问题1

    转自 https://blog.csdn.net/xuehu837769474/article/details/80603898 1.安卓浏览器看背景图片,有些设备会模糊. 用同等比例的图片在PC机上 ...

  4. centos7 nginx 配置 ssl证书

    安装nginx 从阿里云服务器下载 nginx版本的ssl证书,防止再 /etc/nginx/ssl 下 停止 nginx 服务 systemctl stop nginx 修改配置文件 /etc/ng ...

  5. Jenkins运行python脚本出现 configparser.NoSectionError: No section: 'XXXXXX'

    原来的代码如下: def get_test_config(tag, key, config="config.ini"): cf = configparser.ConfigParse ...

  6. 18 IO流(十五)——RandomAccessFile随机访问文件及使用它进行大文件切割的方法

    本文部分内容转自:https://blog.csdn.net/nightcurtis/article/details/51384126 1.RandomAccessFile特点 RandomAcces ...

  7. golang 实现定时任务

    在实际开发过程中,我们有时候需要编写一些定时任务.当然我们可以使用crontab命令实现我们的需求.但是这种方法不满足一些定制化场景,同时会依赖具体的操作系统环境. 定时任务 在golang中我们可以 ...

  8. BBR 安装

    谷歌云申请搭建翻墙 1.申请谷歌账号 2.申请免费一年谷歌云使用 https://console.cloud.google.com/ 3.设置客户端 xshell/ putty ssh客户端设置 vi ...

  9. ffmpeg 速查手册

    ref : http://linux.51yip.com/search/ffmpeg ffmpeg是一个源于Linux的工具软件,是FLV视频转换器,可以轻易地实现FLV向其它格式avi.asf. m ...

  10. MOOC web前端开发笔记(二)

    HTML HTML概述 HTML(HyperText MarkUp Language) "超文本标记语言",以标签的形式规定网页结构,它是制作网页的标准语言 HTML不区分大小写 ...