博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #446 (Div. 2)
阅读量:4992 次
发布时间:2019-06-12

本文共 6792 字,大约阅读时间需要 22 分钟。

目录

Codeforces Round #446 (Div. 2)

  • 总体:rating涨了好多,虽然有部分是靠和一些大佬(例如 redbagHometown )交流的……希望下次能自己做出来2333

A. Greed

题意

给你\(n\)个罐子,每个罐子都告诉了你它当前的饮料体积和它的总容积,问能否用两个罐子装下所有饮料(\(n\le 100000\)

题解

简单模拟即可,用两个最大的算一下,注意累和会爆\(int\)

int a[100100], b[100100];long long sum = 0;int main () {    int n = read();    For (i, 1, n) {        a[i] = read();        sum += a[i];    }    For (i, 1, n)        b[i] = read();    sort (b + 1, b + 1 + n);    if (b[n] + b[n - 1] >= sum)        puts("YES");    else        puts("NO");    return 0;}

B. Wrath

题意

给你一个长度为\(n\)序列,每个点有个\(l\)值,会覆盖他前面\(l\)个点,问最后还剩多少个点没有被覆盖。(\(n\le 100000\)

题解

应该用差分简单做一下就行了,脑子一抽写了个线段树上去,幸亏过了2333(就当练手吧)

代码

const int N = 1e6 + 1e3;int sum[N << 2];#define lson o << 1, l, mid#define rson o << 1 | 1, mid + 1, r void Build(int o, int l, int r) {    if (l == r) { sum[o] = 1; return ; }    int mid = (l + r) >> 1;    Build(lson); Build(rson);    sum[o] = sum[o << 1] + sum[o << 1 | 1];}int ul, ur;int lazy[N << 2];void push_down(int o) {    if (!lazy[o]) return;    lazy[o << 1] = lazy[o << 1 | 1] = 1;     sum[o << 1] = sum[o << 1 | 1] = 0; lazy[o] = 0; }void Update(int o, int l, int r) {    if (ul <= l && r <= ur) { lazy[o] = 1; sum[o] = 0; return ;}    push_down(o); int mid = (l + r) >> 1;    if (ul <= mid) Update(lson); if (ur > mid) Update(rson);    sum[o] = sum[o << 1] + sum[o << 1 | 1];}int main () {    int n = read();    Build(1, 1, n);    For (i, 1, n) {        int len = read();        if (i == 1) continue ;        if (!len) continue ;        ul = max(i - len, 1); ur = i - 1;        Update(1, 1, n);    }    printf ("%d\n", sum[1]);    return 0;}

C. Pride

题意

给你一个长为\(n\)序列,你能进行一个操作,将相邻两个数中的一个替换为他们的\(gcd\),问至少进行多少次操作能把他们全部变成\(1\),如果不能完成输出\(-1\)。(\(n\le 2000\)

题解

这题一开始搞了我好久QAQ,想错了。其实就是先弄出一个\(1\),然后可以把其他所有的数字都变成\(1\),剩下的步数就是\(n-1\)。找那个步数,一定是一段连续区间\(gcd=1\)的情况,然后你用\(O(n^2)\)去枚举一下,找到一个可行的最小长度。还需要特判一开始就有\(1\)的情况,不然会挂掉(我就惨遭hack了TAT,后来又hack了两个可怜鬼233)。

代码

const int N = 2010;int a[N], n, ans = 0x7f7f7f7f, res, now;int main () {    n = read();    res = n;    For (i, 1, n) {        a[i] = read();        if (a[i] == 1) -- res;          now = __gcd(now, a[i]);    }    if (now != 1)        return puts("-1"), 0;    if (res != n)        return printf ("%d\n", res), 0;    For (i, 1, n) {        int here = a[i], len = 0;        if (here == 1) {            ans = 0;            continue ;        }        Fordown (j, i - 1, 1) {            ++ len;            here = __gcd(here, a[j]);            if (here == 1) {                chkmin(ans, len);                break;            }        }    }    printf ("%d\n", ans + n - 1);    return 0;}

D. Gluttony

题意

给你一个长为\(n\)序列,其中每个数字都不相同,让你输出一个原序列的一个排列,使得他们中任意一个子集(不能为空集或者全集)的和都互不相同(就是相同位置上的数的和互不相同就行了)(\(n\le 22\)

题解

一开始不知道做法,redbag大佬讲出来了正解,就是将每一个数换成后一个比它大的数,最大的数换成最小的那一个,就行了。

证明

这个还是比较好证明的。

考虑分两种情况讨论:

  1. 原子集没有最大的那个数:这就显然是个正确的,每个数都比之前的数要大,所以总和肯定要大;

  2. 原子集有最大的那个数:最大数改变后的值最整个里面最大的,然后你将这个子集去掉最大的那个数,剩下的变化量的和肯定要小于你最大值变为最小值的值,因为你之间肯定会有多余的空格(因为不能为全集)留着,所以肯定是可行的啦。

代码

int n, a[25];struct node {    int val, pos;    bool operator < (const node &rhs) const {        return val < rhs.val;    }};node lt[25];int ans[25];int main () {    n = read();    For (i, 1, n) {        lt[i].val = read();        lt[i].pos = i;    }    sort (lt + 1, lt + 1 + n);    For (i, 1, n)         if (i != n)            ans[lt[i].pos] = lt[i + 1].val;        else             ans[lt[i].pos] = lt[1].val;    For (i, 1, n)        printf ("%d ", ans[i]);    return 0;}

E. Envy

终于来填远古巨坑了。

题意

给你一个有 \(n\) 个点 \(m\) 条边的带边权无向连通图。

\(q\) 次询问,每次询问 \(k\) 条边是否能同时存在于 \(MST\) (最小生成树)中。(不要求在线回答)

\(n, m, q, \sum k \le 5 \times 10^5\)

题解

首先要知道一个很显然的结论。

就是在 \(Kruskal\)\(MST\) 过程中,我们能否把一条边 \((u, v, w)\) 放入 \(MST\) 中,当且仅当 \(<w\) 的所有边联通后,\(u, v\) 仍然不连通。

所以对于每次询问来说,边权不相同的边是互不影响的,我们可以对于这些边权互不相同的边单独考虑。

相同 \(w\) 的如何考虑呢?首先 \(<w\) 的边全部加入,然后对于这些边按任意顺序加入的时候,不能存在 \((u, v)\) 相连的情况。

那么就可以得到一个离线算法了。把所有边权按权值排序,一条条加入。然后对于权值相同的同一询问的边,也逐个加入判断是否可行,最后利用可撤销并查集按秩合并的特性,把当前询问的边撤回就行了。

最后复杂度就是 \(O((m + \sum k) \log n)\) 的。(挂询问用了 std :: map, set 有点慢。。)

代码

还是比较好写的。。

#include 
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)#define Set(a, v) memset(a, v, sizeof(a))#define Cpy(a, b) memcpy(a, b, sizeof(a))#define debug(x) cout << #x << ": " << (x) << endl#define DEBUG(...) fprintf(stderr, __VA_ARGS__)#define fir first#define sec second#define mp make_pairusing namespace std;typedef pair
PII;template
inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }template
inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }inline int read() { int x(0), sgn(1); char ch(getchar()); for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1; for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48); return x * sgn;}void File() {#ifdef zjp_shadow freopen ("E.in", "r", stdin); freopen ("E.out", "w", stdout);#endif}const int N = 5e5 + 1e3;struct Edge { int u, v, w;} lt[N];int Hash[N], tot;struct Data { int u, v, a, b;};namespace Union_Set { int fa[N], height[N]; int find(int x) { return x == fa[x] ? x : find(fa[x]); } Data stk[N]; int top; inline bool Merge(int u, int v, bool flag) { u = find(u); v = find(v); if (u == v) return false; if (flag) stk[++ top] = (Data) {u, v, height[u], height[v]}; if (height[u] > height[v]) swap(u, v); fa[u] = v; if (height[u] == height[v]) ++ height[v]; return true; } inline void Distract() { Data cur = stk[top --]; height[fa[cur.u] = cur.u] = cur.a; height[fa[cur.v] = cur.v] = cur.b; }}bool ans[N];map
> M[N];inline int find_pos(int x) { return lower_bound(Hash + 1, Hash + tot + 1, x) - Hash;}int main () { File(); int n = read(), m = read(); using namespace Union_Set; For (i, 1, n) fa[i] = i; For (i, 1, m) { lt[i].u = read(); lt[i].v = read(); Hash[i] = lt[i].w = read(); } sort(Hash + 1, Hash + m + 1); tot = unique(Hash + 1, Hash + m + 1) - Hash - 1; int q = read(); For (i, 1, m) M[find_pos(lt[i].w)][q + 1].insert(mp(lt[i].u, lt[i].v)); For (i, 1, q) { int k = read(); ans[i] = true; For (j, 1, k) { int id = read(); M[find_pos(lt[id].w)][i].insert(mp(lt[id].u, lt[id].v)); } } For (i, 1, tot) { for (auto itm : M[i]) { if (itm.fir != q + 1 && !ans[itm.fir]) continue ; for (auto its : itm.sec) ans[itm.fir] &= Merge(its.fir, its.sec, itm.fir <= q); while (top) Distract(); } } For (i, 1, q) puts(ans[i] ? "YES" : "NO"); return 0;}

转载于:https://www.cnblogs.com/zjp-shadow/p/7857739.html

你可能感兴趣的文章
inline必须在定义、实现都标记
查看>>
从单链表到循环链表
查看>>
百度招聘无处不在!
查看>>
丢失控制文件恢复实验记录--3(当前的控制文件损坏,归档日志文件损坏且备份的控制文件是旧的情况恢复数据库)...
查看>>
Ganglia监控MySQL
查看>>
反射和动态导入模块
查看>>
信息社会
查看>>
Mysql存储引擎概念特点介绍及不同业务场景选用依据
查看>>
关于Java类Calendar做统计时 获取日期的一些常见操作
查看>>
从程序员转向淘宝店主的探索
查看>>
openstack 中国联盟公开课參会总结
查看>>
约瑟夫环问题详解 (c++)
查看>>
Ubuntu 配置VNC以及使用VNC连接时,无法显示系统菜单栏,解决方法
查看>>
BZOJ.3990.[SDOI2015]排序(DFS)
查看>>
hdu 1358
查看>>
“-fembed-bitcode is not supported on versions of iOS prior to 6.0” 错误
查看>>
[转]jquery mobile中redirect重定向问题
查看>>
[django]表格的添加与删除实例(可以借鉴参考)
查看>>
Mockito一个采用Java编写用于单元测试的Mocking框架
查看>>
把elipse非maven的Struts2+Spring+Ibatis项目导入Idea中
查看>>