Codeforces Round #535 (Div. 3) 解题报告
CF1108A. Two distinct points
做法:模拟
如果两者左端点重合就第二条的左端点++就好,然后输出左端点
#include <bits/stdc++.h>
using namespace std;
int T;
int l1, r1, l2, r2;
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
printf("%d ", l1);
if(l1 == l2) l2++;
printf("%d\n", l2);
}
}
CF1108B. Divisors of Two Integers
做法:模拟
坑点好多...首先因为所有因数都有,所以最大的数一定是x,y中的一个.把它拎出来,然后删掉它的因子,剩下的最大的就是x,y中的另外一个了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int a[100000];
int cnt[101000];
int main() {
scanf("%d", &n);
int mx = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
cnt[a[i]]++;
mx = max(mx, a[i]);
}
printf("%d ", mx);
for(int i = 1; i * i <= mx; ++i) {
if(mx % i == 0) {
cnt[i]--;
if(mx / i != i) cnt[mx / i]--;
}
}
int ans = 0;
for(int i = 1; i <= mx; ++i) {
if(cnt[i] > 0) ans = i;
}
printf("%d\n", ans);
}
CF1108C. Nice Garland
做法:模拟
依旧是模拟qwq.显然合法的排列方式也就那么6种...于是6种方式都跑一遍,然后取min即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, id = 0;
char s[N];
string f[6] = {"RGB", "RBG", "BRG", "BGR", "GRB", "GBR"};
int main() {
scanf("%d%s", &n, s + 1);
int ans = N;
for(int k = 0; k < 6; ++k) {
int sum = 0, pos = 0;
for(int i = 1; i <= n; ++i, pos = (pos + 1) % 3) {
if(s[i] != f[k][pos]) ++sum;
}
if(sum < ans) {
ans = sum;
id = k;
}
}
printf("%d\n", ans);
for(int i = 1, pos = 0; i <= n; ++i, pos = (pos + 1) % 3) putchar(f[id][pos]);
}
CF1108D. Diverse Garland
做法:dp
第一问显然sb dp,设f[i,j]表示点i然后点i填的是RGB中的一个(分别对应一个j),直接转移即可.输出方案反而比较难,有各种方法,我的方法是记录每个dp值的转移点,从后往前推回去.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, id = 0;
char s[N], p[3] = {'R', 'G', 'B'};
int f[N][3], to[N][3];
char t[N];
int main() {
scanf("%d%s", &n, s + 1);
memset(f, 0x3f, sizeof(f));
f[1][0] = f[1][1] = f[1][2] = 1;
if(s[1] == 'R') f[1][0] = 0;
else if(s[1] == 'G') f[1][1] = 0;
else f[1][2] = 0;
for(int i = 2; i <= n; ++i)
for(int j = 0; j < 3; ++j)
for(int k = 0; k < 3; ++k) {
if(j == k) continue;
if(p[j] == s[i]) {
if(f[i - 1][k] < f[i][j])
f[i][j] = f[i - 1][k], to[i][j] = k;
} else {
if(f[i - 1][k] + 1 < f[i][j])
f[i][j] = f[i - 1][k] + 1, to[i][j] = k;
}
}
int ans = 0, id = 0;
if(f[n][0] > f[n][1]) {
ans = f[n][1], id = 1;
} else ans = f[n][0], id = 0;
if(f[n][2] < ans) ans = f[n][2], id = 2;
printf("%d\n", ans);
for(int i = n; i; i--) {
t[i] = p[id];
id = to[i][id];
}
for(int i = 1; i <= n; ++i) putchar(t[i]); puts("");
return 0;
}
CF1108E1. Array and Segments (Easy version)
做法:暴力
考虑怎么样才能让结果最大,把线段分成两类,一种是没有覆盖最大值,一种是有覆盖最大值的,如果选了覆盖最大值的显然只会减小答案,所以可以暴力枚举最大值,并累加不覆盖最大值的线段,对所有情况取max即可复杂度是\(O(n^2m)\)的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int inf = 0x3f3f3f3f;
int n, m, a[N], b[N];
int vis[N];
struct seg {
int l, r, id;
} s[N];
vector<int> Ans;
int ans = -1;
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= m; ++i) scanf("%d%d", &s[i].l, &s[i].r), s[i].id = i;
for(int i = 1; i <= n; ++i) {
vector<int> cur; cur.clear();
int lans = 0;
for(int j = 1; j <= n; ++j) b[j] = a[j];
for(int j = 1; j <= m; ++j) {
if(s[j].l <= i && i <= s[j].r) continue;
for(int k = s[j].l; k <= s[j].r; ++k) b[k]--;
cur.push_back(j);
}
for(int j = 1; j <= n; ++j) {
if(j == i) continue;
lans = max(lans, a[i] - b[j]);
}
if(lans > ans) {
ans = lans;
Ans = cur;
}
}
sort(Ans.begin(), Ans.end());
printf("%d\n%d\n", ans, (int)Ans.size());
for(int i = 0, len = Ans.size(); i < len; ++i) {
printf("%d ", Ans[i]);
}
return 0;
}
CF1108E2. Array and Segments (Hard version)
做法:线段树优化暴力
考虑优化E1的暴力,注意到m很小,所以复杂度里面是可以有一个m的.然后利用线段树来优化把线段覆盖下去的过程,即利用线段树维护区间修改,维护区间min.这样的复杂度是\(O(nmlogn)\)的.这样朴素的去做会TLE on 12.发现每次如果加入线段然后再删除线段会有很多重复的操作,可以拿一个数组来标记哪条线段有覆盖哪条没有,如果有线段不能覆盖下去且已经覆盖了,那么就+1回去,能覆盖下去的同理,这样修改次数就大大降低了.这样就能通过本题了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int n, m, a[N], b[N];
struct seg {
int l, r, id;
} s[N];
vector<int> Ans;
int ans = -1;
struct tree {
int l, r, mn, tag;
} t[N<<2];
#define lc (rt << 1)
#define rc (rt << 1 | 1)
void pushup(int rt) { t[rt].mn = min(t[lc].mn, t[rc].mn); }
void build(int l, int r, int rt) {
t[rt].l = l; t[rt].r = r; t[rt].mn = inf;
if(l == r) { t[rt].mn = a[l]; return; }
int mid = (l + r) >> 1;
build(l, mid, lc); build(mid + 1, r, rc); pushup(rt);
}
void pushdown(int rt) {
if(t[rt].tag) {
int &x = t[rt].tag;
t[lc].tag += x; t[rc].tag += x;
t[lc].mn += x; t[rc].mn += x;
x = 0;
}
}
#define l (t[rt].l)
#define r (t[rt].r)
void upd(int L, int R, int c, int rt) {
if(L <= l && r <= R) {
t[rt].tag += c; t[rt].mn += c;
return;
}
pushdown(rt); int mid = (l + r) >> 1;
if(L <= mid) upd(L, R, c, lc);
if(R > mid) upd(L, R, c, rc);
pushup(rt);
}
#undef l
#undef r
#undef lc
#undef rc
bool vis[N];
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= m; ++i) scanf("%d%d", &s[i].l, &s[i].r), s[i].id = i;
build(1, n, 1);
for(int i = 1; i <= n; ++i) {
vector<int> cur; cur.clear();
int lans = 0;
for(int j = 1; j <= m; ++j) {
if(s[j].l <= i && i <= s[j].r) {
if(vis[j]) {
vis[j] = 0;
upd(s[j].l, s[j].r, 1, 1);
}
} else {
if(!vis[j]) vis[j] = 1, upd(s[j].l, s[j].r, -1, 1);
cur.push_back(j);
}
}
lans = max(0, a[i] - t[1].mn);
if(lans > ans) {
ans = lans;
Ans = cur;
}
}
sort(Ans.begin(), Ans.end());
printf("%d\n%d\n", ans, (int)Ans.size());
for(int i = 0, len = Ans.size(); i < len; ++i) {
printf("%d ", Ans[i]);
}
return 0;
}
CF1108F. MST Unification
做法:最小生成树
考虑怎么样才会使一个最小生成树不唯一.设有一条边边权为val,且它没有在最小生成树中,那么加入最小生成树之后,就会出来一个环,如果这个环中有一条边边权为val,那么这个mst就是不唯一的.可以倍增实现这个过程但是比较麻烦,也可以选择就是对所有边权相同的边权统一考虑一下:如果此边的两个端点已经在最小生成树里面了,那么显然这条边对mst的唯一性没有影响(因为连接它的边边权一定更小),不用管它.如果两端点之前还未接入最小生成树,但是在加到这条边的时候又已经加入了(即有同样长度的边使两端点联通),那么这条边就一定会对答案产生影响,需要+1保证mst的唯一性
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010;
struct edge {
int x, y, v;
} e[N];
int n, m, f[N];
bool cmp(edge a, edge b) {
return a.v < b.v;
}
int find(int x) {
if(f[x] == x) return x;
else return f[x] = find(f[x]);
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].v);
}
sort(e + 1, e + m + 1, cmp);
for(int i = 1; i <= n; ++i) f[i] = i;
int ans = 0;
for(int i = 1, j = 1; i <= m; i = j) {
while(j <= m && e[j].v == e[i].v) ++j;
int tot = j - i;
for(int k = i; k < j; ++k) {
int x = find(e[k].x), y = find(e[k].y);
if(x == y) --tot;
}
for(int k = i; k < j; ++k) {
int x = find(e[k].x), y = find(e[k].y);
if(x == y) continue;
f[x] = y;
--tot;
}
ans += tot;
}
printf("%d\n", ans);
}
Codeforces Round #535 (Div. 3) 解题报告的更多相关文章
- Codeforces Round #324 (Div. 2)解题报告
---恢复内容开始--- Codeforces Round #324 (Div. 2) Problem A 题目大意:给二个数n.t,求一个n位数能够被t整除,存在多组解时输出任意一组,不存在时输出“ ...
- Codeforces Round #382 (Div. 2) 解题报告
CF一如既往在深夜举行,我也一如既往在周三上午的C++课上进行了virtual participation.这次div2的题目除了E题都水的一塌糊涂,参赛时的E题最后也没有几个参赛者AC,排名又成为了 ...
- Codeforces Round #380 (Div. 2) 解题报告
第一次全程参加的CF比赛(虽然过了D题之后就开始干别的去了),人生第一次codeforces上分--(或许之前的比赛如果都参加全程也不会那么惨吧),终于回到了specialist的行列,感动~.虽然最 ...
- Codeforces Round #216 (Div. 2)解题报告
又范低级错误! 只做了两题!一道还被HACK了,囧! A:看了很久!应该是到语文题: 代码:#include<iostream> #include<]; ,m2=; ;i ...
- Codeforces Round #281 (Div. 2) 解题报告
题目地址:http://codeforces.com/contest/493 A题 写完后就交了,然后WA了,又读了一遍题,没找出错误后就开始搞B题了,后来回头重做的时候才发现,球员被红牌罚下场后还可 ...
- Codeforces Round #277 (Div. 2) 解题报告
题目地址:http://codeforces.com/contest/486 A题.Calculating Function 奇偶性判断,简单推导公式. #include<cstdio> ...
- Codeforces Round #276 (Div. 2) 解题报告
题目地址:http://codeforces.com/contest/485 A题.Factory 模拟.判断是否出现循环,如果出现,肯定不可能. 代码: #include<cstdio> ...
- Codeforces Round #350 (Div. 2)解题报告
codeforces 670A. Holidays 题目链接: http://codeforces.com/contest/670/problem/A 题意: A. Holidays On the p ...
- Codeforces Round #479 (Div. 3)解题报告
题目链接: http://codeforces.com/contest/977 A. Wrong Subtraction 题意 给定一个数x,求n次操作输出.操作规则:10的倍数则除10,否则减1 直 ...
随机推荐
- Python全栈-库的操作
一.系统数据库 安装数据库系统后,系统自带的数据库.通过mysql客户端连接数据库系统后,使用show命令可查看系统中存在的所有库: mysql> show databases; +------ ...
- GameObject.Find与Transform.Find的区别
1.GameObject.Find 函数原型: public static GameObject Find(string name); 说明:1.GameObject只能查找到active的物体 2. ...
- 记一次CentOS5.7更新glibc导致libc.so.6失效,系统无法启动
以下是错误示范,错误过程还原,请勿模仿!!! wkhtmltopdf 启动,提示/lib64/libc.so.6版本过低 $ ./wkhtmltopdf http:www.baidu.com 1. ...
- sitecore系统教程之架构概述
Sitecore体验数据库(xDB)从实时大数据存储库中的所有通道源收集所有客户交互.它连接交互数据,为每个客户创建全面,统一的视图,并使营销人员可以使用数据来管理客户的实时体验. xDB架构非常灵活 ...
- 解决 samba 服务器 windows 多重连接
samba连接,用户名密码均正确.失败提示:不允许一个用户使用一个以上用户名与一个服务器或共享资源的多重连接. 事实上,这个不是samba的限制.是Windows的限制. 在打开存在public = ...
- 设计模式之Memento(备忘机制)(转)
Memento定义: memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态. Memento模式相对也比较好理解,我们看下列代码: public clas ...
- react+redux+react-router+node.js 开发实时聊天App 学习记录
一.课程导学 1.React 主要解决的是UI层的问题,应用的状态需要借助Redux等状态管理. 2.前端React + antd-mobile UI组件库 + Redux 状态管理库 + Rea ...
- div居中与div内容居中,不一样
1.div自身居中 使用margin:0 auto上下为0,左右自适应的css样式. 要让div水平居中,那么除了设置css margin:0 auto外,还不能再设置float,不然将会导致div靠 ...
- hdu1599 find the mincost route
题目链接 floyd找最小环 很好理解 #include<algorithm> #include<iostream> #include<cstdlib> #incl ...
- bzoj4358 premu
题目链接 莫队算法 没有用线段树,而是看了showson的并查集%%% #include<algorithm> #include<iostream> #include<c ...