Virtual participate 的,D题不会做,打了1:30就打不动了,过了ABCE。

A - CME

题意:?

题解:?

void test_case() {
int n;
scanf("%d", &n);
if(n == 2)
puts("2");
else
printf("%d\n", n & 1);
}

B - Strings Equalization

题意:给两个等长的字符串,每次可以把一个字母赋值给它前一个和后一个,问两个字符串能否变成相等。

题解:判断有没有相同的字母。

/

int cnt1[26], cnt2[26];

char s[2000], t[2000];
void test_case() {
scanf("%s%s", s + 1, t + 1);
for(int i = 0; i < 26; ++i)
cnt1[i] = cnt2[i] = 0;
int l = strlen(s + 1);
for(int i = 1; i <= l; ++i)
cnt1[s[i] - 'a']++;
for(int i = 1; i <= l; ++i)
cnt2[t[i] - 'a']++; for(int i = 0; i < 26; ++i) {
if(cnt1[i] && cnt2[i]) {
puts("YES");
return;
}
}
puts("NO");
}

C - Save the Nature

题意:电影院规定a的倍数的票的x%以及b的倍数的票的y%会捐赠出去,求捐赠出至少k元需要的最小的电影票数量。你可以任意排列这些电影票,而且a和b的公倍数会捐(x+y)%。

题解:很显然的二分题,直接二分电影票的数量t,然后取前t大的电影票出来。先贪心分给公倍数,然后贪心分给比例更大的那个,最后的全部尝试分给比例小的那个。

int n;
int p[200005];
int tp[200005];
int x, a, y, b;
ll g, k; bool check(int t) {
ll cur = 0;
int i = 1;
int restg = t / g;
int resta = t / a - restg, restb = t / b - restg;
while(i <= t) {
if(restg) {
--restg;
cur += 1ll * tp[i] * (x + y) / 100;
} else if(resta) {
--resta;
cur += 1ll * tp[i] * x / 100;
} else if(restb) {
--restb;
cur += 1ll * tp[i] * y / 100;
} else
break;
++i;
}
return cur >= k;
} int bs() {
int L = 1, R = n;
while(1) {
int M = (L + R) >> 1;
if(L == M) {
if(check(L))
return L;
if(check(R))
return R;
return -1;
}
if(check(M))
R = M;
else
L = M + 1;
}
} void test_case() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &p[i]);
tp[i] = p[i];
}
sort(tp + 1, tp + 1 + n, greater<int>());
scanf("%d%d%d%d%lld", &x, &a, &y, &b, &k);
if(y > x) {
swap(x, y);
swap(a, b);
}
g = 1ll * a * b / __gcd(a, b);
printf("%d\n", bs());
}

其实上面没有必要再开一个tp数组。而且可以求出tp数组的前缀和,这样验证就不是O(t)了而是O(1)。

int n;
ll p[200005];
int x, a, y, b;
ll g, k; bool check(int t) {
int rg = t / g;
int ra = t / a - rg, rb = t / b - rg;
ll cur = (p[rg] * (x + y) + (p[rg + ra] - p[rg]) * x + (p[rg + ra + rb] - p[rg + ra]) * y);
return cur >= k;
} int bs() {
int L = 1, R = n;
while(1) {
int M = (L + R) >> 1;
if(L == M) {
if(check(L))
return L;
if(check(R))
return R;
return -1;
}
if(check(M))
R = M;
else
L = M + 1;
}
} void test_case() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld", &p[i]);
sort(p + 1, p + 1 + n, greater<ll>());
for(int i = 1; i <= n; ++i)
p[i] += p[i - 1];
scanf("%d%d%d%d%lld", &x, &a, &y, &b, &k);
k *= 100;
if(y > x) {
swap(x, y);
swap(a, b);
}
g = 1ll * a * b / __gcd(a, b);
printf("%d\n", bs());
}

D

参考资料:https://blog.csdn.net/Dch19990825/article/details/103017653

E - Paint the Tree

题意:将一棵n个节点的树,边带正权,每个节点染恰好k种颜色,且每种颜色至多染2个节点,问最大权值的染色方法。

题解:一开始往生成树那里想了,以为是先取权最大的边贪心,这个反例很好举的,怎么会这么演呢?后面想了想会不会是树形dp呢?只需要考虑儿子的颜色满了和没满两种情况,而根本不关心子树的细节。

所以设置dp[u][0]为u节点颜色没满的以u为根的子树的最大权和,dp[u][1]为u节点的颜色满了没满的最大权和,所以dp[u][1]>=dp[u][0]。

先特判掉没有边的情况,免得乱七八糟的。然后度为1的点也不是根节点的点就一定是叶子,叶子直接返回。

否则,一棵树肯定是可以不取去往子树的边的,所以直接取dp[v][1]出来,同时假如取子树的边,那么值会增加:w+dp[v][0]-dp[v][1],把这个存在每层dfs中的tmp数组里,假如怕爆栈就放在tmp[u]中就可以了(这里确实会怕爆栈的问题?不太清楚vector是怎么分配空间的,分配的是堆空间还是栈空间?),这里可以不取ll,因为dp[v][0]和dp[v][1]的差应该不太会超过一条边的权(感觉是因为dp[v][1]最多就是比dp[v][0]多取了一条边罢了,不过最好下次还是要用ll)。

对tmp数组排序。取出最大的最多k-1个更新dp[u][0]和dp[u][1],假如还有第k个可以再更新dp[u][1]。

int n, k;
vector<pii>G[500005];
ll dp[500005][2]; void dfs(int u, int p) {
if(G[u].size() == 1 && p != -1) {
//printf("dp[%d][%d]=%lld\n", u, 0, dp[u][0]);
//printf("dp[%d][%d]=%lld\n", u, 1, dp[u][1]);
return;
}
vector<pii>tmp;
for(auto &e : G[u]) {
int v = e.first, w = e.second;
if(v == p)
continue;
dfs(v, u);
dp[u][0] += dp[v][1];
dp[u][1] += dp[v][1];
if(w + dp[v][0] - dp[v][1] > 0)
tmp.push_back({w + dp[v][0] - dp[v][1], v});
}
sort(tmp.begin(), tmp.end(), greater<pii>());
int c = min((int)tmp.size(), k - 1);
for(int i = 0; i < c; ++i) {
dp[u][0] += tmp[i].first;
dp[u][1] += tmp[i].first;
}
dp[u][1] += tmp.size() >= k ? tmp[k - 1].first : 0;
//printf("dp[%d][%d]=%lld\n", u, 0, dp[u][0]);
//printf("dp[%d][%d]=%lld\n", u, 1, dp[u][1]);
assert(dp[u][1]>=dp[u][0]);
} void test_case() {
scanf("%d%d", &n, &k);
if(n == 1) {
puts("0");
return;
}
for(int i = 1; i <= n; ++i) {
dp[i][0] = 0;
dp[i][1] = 0;
G[i].clear();
}
for(int i = 1; i <= n - 1; ++i) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].push_back({v, w});
G[v].push_back({u, w});
}
dfs(1, -1);
printf("%lld\n", dp[1][1]);
}

可是我为什么写不出D呢?

Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1)的更多相关文章

  1. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature【枚举二分答案】

    https://codeforces.com/contest/1241/problem/C You are an environmental activist at heart but the rea ...

  2. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) D. Sequence Sorting

    链接: https://codeforces.com/contest/1241/problem/D 题意: You are given a sequence a1,a2,-,an, consistin ...

  3. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) B. Strings Equalization

    链接: https://codeforces.com/contest/1241/problem/B 题意: You are given two strings of equal length s an ...

  4. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature

    链接: https://codeforces.com/contest/1241/problem/C 题意: You are an environmental activist at heart but ...

  5. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) A. CME

    链接: https://codeforces.com/contest/1241/problem/A 题意: Let's denote correct match equation (we will d ...

  6. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) 题解

    A..B略 C 对当前的值排序,再二分答案,然后对于(i%x==0 && i%y==0)放入大的,再放其他的贪心解决即可. #include<iostream> #incl ...

  7. Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2)

    A - Forgetting Things 题意:给 \(a,b\) 两个数字的开头数字(1~9),求使得等式 \(a=b-1\) 成立的一组 \(a,b\) ,无解输出-1. 题解:很显然只有 \( ...

  8. Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3

    A,有多个线段,求一条最短的线段长度,能过覆盖到所又线段,例如(2,4)和(5,6) 那么我们需要4 5连起来,长度为1,例如(2,10)(3,11),用(3,10) 思路:我们想一下如果题目说的是最 ...

  9. 【cf比赛记录】Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4)

    比赛传送门 只能说当晚状态不佳吧,有点头疼感冒的症状.也跟脑子没转过来有关系,A题最后一步爆搜没能立即想出来,B题搜索没有用好STL,C题也因为前面两题弄崩了心态,最后,果然掉分了. A:简单数学 B ...

随机推荐

  1. 数据结构之链表(LinkedList)(二)

    数据结构之链表(LinkedList)(一) 双链表 上一篇讲述了单链表是通过next 指向下一个节点,那么双链表就是指不止可以顺序指向下一个节点,还可以通过prior域逆序指向上一个节点 示意图: ...

  2. 【转载】Asp.Net中Cookie对象的作用以及常见属性

    Cookie对象是服务器为用户访问存储的特定信息,这些信息一般存储在浏览器中,服务器可以从提交的数据中获取到相应的Cookie信息,Cookie的最大用途在于服务器对用户身份的确认,即票据认证,用户会 ...

  3. HTML的发展历史

    HTML是Web统一语言,这些容纳在尖括号里的简单标签,构成了如今的Web,1991年,Tim Berners-Lee编写了一份叫做“HTML标签”的文档,里面包含了大约20个用来标记网页的HTML标 ...

  4. pc端vue 滚动到底部翻页

    html: <div class="list" ref="scrollTopList"> <div class="listsmall ...

  5. 【前端适配】vw单位移动端适配方案

    近些年移动端的强势崛起,导致移动端适配越来越重要,个人之前一直使用的是rem进行适配,但是发现并不是非常完美,给力的是大漠老师写了一篇<如何在Vue项目中使用vw实现移动端适配>,比较完美 ...

  6. windows RabbitMQ Server 环境配置中的一些坑

    原文:https://blog.csdn.net/lindonglian/article/details/55805637 RabbitMQ的服务端基于Erlang语言编写,要在机器上安装Rabbit ...

  7. ElasticSearch 连载一 基础入门

    ElasticSearch简写ES,ES是一个高扩展.开源的全文检索和分析引擎,它可以准实时地快速存储.搜索.分析海量的数据. 应用场景 我们常见的商城商品的搜索 日志分析系统(ELK) 基于大量数据 ...

  8. ES6 解构赋值详解

    解构赋值是对赋值运算符的扩展,可以将属性/值从对象/数组中取出,赋值给其他变量. 一.数组的解构赋值 1.基本用法 只要等号两边的模式相同,左边的变量就会被赋予对应的值. let [a, [[b], ...

  9. Java对象内存分配原理与布局

    当一个对象被创建了,那在JVM中是如何的从一个对象不存在到存到,然后将对象存放在什么地方呢?这次主要来探讨一下Java对象创建的过程. new关键字创建对象的3个步骤: 1.在堆内存中创建出对象的实例 ...

  10. prometheus监控redis,redis-cluster

    Prometheus监控redis使用的是redis_exporter, 作者GitHub: https://github.com/oliver006/redis_exporter 需要说明的是: r ...