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. Python虚拟环境Virtualen简单使用

    安装pip 使用脚本安装和升级pip 要安装或升级pip,需要下载 get-pip.py. 地址:https://bootstrap.pypa.io/get-pip.py 然后运行以下命令 (需要管理 ...

  2. LeetCode 75. 颜色分类(Sort Colors) 30

    75. 颜色分类 75. Sort Colors 题目描述 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中, ...

  3. C语言中的共用体(union)和枚举(enum)

    1 union union Data{ int i; char ch; float f; }a={1, 'a', 1.5}; //错误 union Data a = {16}; //正确 union ...

  4. (父向子传值)组件内的properties类似与vue中的prop接收外界传递进来的参数

    =================================================== 外界引用组件的时候 传递方法  父传子

  5. TypeScript之枚举

    什么是枚举类型,有什么作用? 枚举类型就是一个用来组织一些有相似之处的常量的对象,作用就是管理常量,让常量更规范,统一.例: enum Direction { Up = 1, Down, Left, ...

  6. Exception: HTTP 599: SSL certificate problem: unable to get local issuer certificate 解决办法

    使用Pyspider中报此错误. 错误原因: 这个错误会发生在请求 https 开头的网址,SSL 验证错误,证书有误. 解决方法: 使用self.crawl(url, callback=self.i ...

  7. EasyARM-iMX283 安装NFS

    1. 安装NFS软件包在 ubuntu 上请输入下面命令:[chenxibing@localhost ~]$ sudo apt-get install nfs-kernel-server[chenxi ...

  8. 5_PHP数组_3_数组处理函数及其应用_2_数组统计函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 一.数组统计函数 数组统计函数是指统计数组各元素的值,并对这些值进行简单分析. 1. count() 函数 该函数 ...

  9. RAS非对称加密

    加解密密钥不一致,一般私钥不公开,使用公钥加密,私钥解密,使用私钥加密,公钥可以解密. java代码 import javax.crypto.Cipher; import java.security. ...

  10. 【转载】 C#使用Math.PI常量来表示圆周率

    在C#中计算圆形面积的时候,我们时常会用到圆周率这个变量,圆周率我们一般定义为十进制decimal类型变量,圆周率的值为3.1415926535等一个近似值,其实在C#的数值计算类Math类中,有专门 ...