Codeforces Round #442 Div.2 A B C D E
A. Alex and broken contest
题意
判断一个字符串内出现五个给定的子串多少次。
Code
#include <bits/stdc++.h>
char s[110];
using namespace std;
typedef long long LL;
char* rec[5] = {"Danil", "Olya", "Slava", "Ann", "Nikita"};
int len[5] = {5,4,5,3,6};
bool cmp(char* s1, char* s2, int len) {
for (int i = 0; i < len; ++i) {
if (s1[i] != s2[i]) return false;
}
return true;
}
int main() {
int cnt=0;
scanf("%s", s);
for (int i = 0; s[i]; ++i) {
for (int j = 0; j < 5; ++j) {
if (cmp(rec[j], s+i, len[j])) ++cnt;
}
if (cnt > 2) {printf("NO\n"); return 0;}
}
if (cnt==1) printf("YES\n");
else printf("NO\n");
return 0;
}
B. Nikita and string
题意
给定一个长为\(n(n\leq 5000)\)的只含\('a',b'\)的字符串,先要求删去最少数目的字符,使得留下的字符串可以被分为三截,最左边全\('a'\),中间一段全\('b'\),最右边全\('a'\).
思路
\(O(n^2)\)
预处理前缀和。
枚举两个分界点。
时间复杂度\(O(n^2)\).
\(O(n)\)
\(dp\)做法
参见http://codeforces.com/contest/877/submission/31663633
Code
#include <bits/stdc++.h>
#define maxn 5010
char s[maxn];
int a[maxn], b[maxn];
using namespace std;
typedef long long LL;
int main() {
scanf("%s", s+1);
int len = strlen(s+1);
for (int i = 1; i <= len; ++i) {
a[i] = a[i-1], b[i] = b[i-1];
if (s[i]=='a') ++a[i];
else ++b[i];
}
int ans = len+1;
for (int i = 1; i <= len+1; ++i) {
for (int j = i; j <= len+1; ++j) {
int x1=0, x2=0, x3=0;
if (i > 1) x1 = b[i-1]-b[0];
if (j > i) x2 = a[j-1]-a[i-1];
if (j <= len) x3 = b[len]-b[j-1];
ans = min(ans,x1+x2+x3);
}
}
printf("%d\n", len-ans);
return 0;
}
C. Slava and tanks
题意
有\(1\times n\)的格子,里面不知道哪些位置会有坦克。每架坦克的血量为\(2\). 在位置\(i\)处扔炸弹,该位置的坦克受到一点伤害,并且跑到相邻的格子中去;再受到一次伤害,就死了。问最少扔多少次炸弹能保证消灭所有的坦克,并且输出扔炸弹的序列。
思路
仆の思路
左右两块:两格两格一组地扔;中间:根据%4的值分类讨论。
有点难描述,直接看代码吧Orz
题解
先往所有偶数格子中扔,再往所有奇数格子中扔,最后往所有偶数格子中扔。
证明
1. 可行性:
先往偶数格子中扔炸弹时,偶数格子中的所有坦克都跑到了奇数格子中;
此时,只有奇数格子中有坦克,且其中的坦克分为两类:血量为\(1\),血量为\(2\)再往奇数格子中扔炸弹,奇数格子中 1) 血量为\(1\)的坦克全都死了; 2) 血量为\(2\)的坦克都跑到了偶数格子中;
此时,只有偶数格子中有坦克,且其中的坦克只有一类:血量为\(1\)最后往偶数格子中扔坦克,全都死了
至于为什么是\(偶\rightarrow 奇\rightarrow 偶\)的顺序而不是\(奇\rightarrow 偶\rightarrow 奇\)的顺序,是因为奇数格子数目\(\geq\)偶数格子数目,所以前者是\(n+n/2\)而后者在\(n\)为奇数时是\(n+n/2+1\).
2. 最优性:
参考题解页面\(ludo\)用户的评论
"
The problem is equivalent to finding a string S such that for all 1 < i ≤ n, i - 1 precedes i somewhere in the string and i precedes i - 1 somewhere in the string.
Now observe that for some i, it occurs either 1 or 2 times in the optimal string. If it is more than 2 times, we can erase the middle ones and obtain a better string.
If for some i, the number of times is 1, then i + 1 must occur (at least) 2 times: to the left of this location and to the right. If i occurs 2 times, then i + 1 must occur (at least) once (in between the two occurences).
From this, you can build the string 2,4,6,... 1,3,5,..., 2,4,6, ... which is therefore optimal.
At every step we get some partial string with all the numbers from 1 to i. Inductively you can show that this is optimal at every transition to i + 1.
"
意思就是说,这个问题等价于找一个串,对于\(1\lt i\leq n\),都有\(i-1\)既在\(i\)之前出现过,也在\(i\)之后出现过。然后在这个转化成的新问题上进行构造。具体见上,就不再翻译了。
转化的依据:当我们轰炸\(i\)位置时,最糟糕的情况是第\(i-1\)个位置和第\(i+1\)个位置上都有坦克。因此,构造出的串中既需要存在\(i,i-1\)这个子串,也需要存在\(i,i+1\)这个子串。换句话说,就是\(i-1\)既在\(i\)之前出现过,也在\(i\)之后出现过。
Code
Ver. 1
#include <bits/stdc++.h>
#define maxn 200010
int ans[maxn];
using namespace std;
typedef long long LL;
int main() {
int n;
scanf("%d", &n);
int tot = 0;
printf("%d\n", n+n/2);
for (int i = 1; i <= n/4; ++i) {
ans[tot++] = i*2;
ans[tot++] = i*2-1;
}
for (int i = 1; i <= n/4; ++i) {
ans[tot++] = n-(i*2)+1;
ans[tot++] = n-(i*2)+2;
}
if (n%4==1) {
ans[tot++] = n/2+1;
for (int i = 2; i < n; ++i) if (!(i&1)) ans[tot++] = i;
}
else if (n%4==3) {
ans[tot++] = n/2+1, ans[tot++] = n/2, ans[tot++] = n/2+2;
for (int i = 2; i < n; ++i) if (!(i&1)) ans[tot++] = i;
}
else if (n%4==2) {
ans[tot++] = n/2; ans[tot++] = n/2+1, ans[tot++] = n/2;
for (int i = 1; i <= n/4; ++i) ans[tot++] = 2*i, ans[tot++] = n+1-2*i;
}
else {
for (int i = 1; i <= n/4; ++i) ans[tot++] = 2 * i, ans[tot++] = n+1-2*i;
}
printf("%d", ans[0]);
for (int i = 1; i < tot; ++i) printf(" %d", ans[i]); printf("\n");
return 0;
}
Ver. 2
#include <bits/stdc++.h>
#define maxn 200010
int ans[maxn];
using namespace std;
typedef long long LL;
int main() {
int n;
scanf("%d", &n);
printf("%d\n", n+n/2);
int tot = 0;
for (int i = 1; i <= n; ++i) if (!(i&1)) ans[tot++]= i;
for (int i = 1; i <= n; ++i) if (i&1) ans[tot++] = i;
for (int i = 1; i <= n; ++i) if (!(i&1)) ans[tot++]= i;
printf("%d", ans[0]);
for (int i = 1; i < tot; ++i) printf(" %d", ans[i]); printf("\n");
return 0;
}
D. Olya and Energy Drinks
题意
给定一张地图,有些地方有障碍物。给定起始点与终止点,可以向上下左右四个方向走。每秒可至多走\(k\)个单位。问最少花多少时间可以从起点到终点。
思路
裸的\(bfs\)
Code
#include <bits/stdc++.h>
#define maxn 1010
struct node { int x, y; };
int dr[4][2] = {{0,1}, {0,-1}, {1,0}, {-1,0}};
char s[maxn];
using namespace std;
typedef long long LL;
bool mp[maxn][maxn];
int v[maxn][maxn];
int main() {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; ++i) {
scanf("%s", s+1);
for (int j = 1; j <= m; ++j) {
if (s[j] == '.') mp[i][j] = 0;
else mp[i][j] = 1;
}
}
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (x1==x2&&y1==y2) { puts("0"); exit(0); }
queue<node> q;
while (!q.empty()) q.pop();
q.push({x1,y1});
while (!q.empty()) {
node nd = q.front(); q.pop();
for (int i = 0; i < 4; ++i) {
node temp = nd;
int step = 0;
while (step < k) {
++step;
temp.x += dr[i][0], temp.y += dr[i][1];
if (temp.x <= 0 || temp.x > n || temp.y <= 0 || temp.y > m || mp[temp.x][temp.y]) break;
if (temp.x == x2 && temp.y == y2) { printf("%d\n", v[nd.x][nd.y]+1); exit(0); }
if (!(temp.x==x1&&temp.y==y1) && !v[temp.x][temp.y]) v[temp.x][temp.y] = v[nd.x][nd.y] + 1, q.push({temp.x, temp.y});
}
}
}
printf("-1\n");
return 0;
}
E. Danil and a Part-time Job
题意
给定一棵有根树,根为\(1\),每个点的值是\(0\)或\(1\). 有两种操作,
- \(get\ v\):询问以\(v\)为根的子树中有多少个点的值为\(1\);
- \(pow\ v\):将以\(v\)为根的子树中所有点的值反转;
思路
\(dfs序+线段树\)
可以说是很裸的题了...
不要脸地来为我原博客里dfs序的文章打下广告_(:з」∠)_ http://blog.csdn.net/kkkkahlua/article/category/7026724
Code
#include <bits/stdc++.h>
#define maxn 200010
#define lson (rt<<1)
#define rson (rt<<1|1)
struct node { int l, r, c, tag; }tr[maxn * 4];
struct Edge { int to, ne; }edge[maxn];
int c[maxn], l[maxn], r[maxn], cnt, tot, ne[maxn];
using namespace std;
typedef long long LL;
void add(int u, int v) {
edge[tot] = {v, ne[u]};
ne[u] = tot++;
}
void dfs(int u) {
l[u] = ++cnt;
for (int i = ne[u]; ~i; i = edge[i].ne) dfs(edge[i].to);
r[u] = cnt;
}
void push_up(int rt) { tr[rt].c = tr[lson].c + tr[rson].c; }
void build(int rt, int l, int r) {
tr[rt].l = l, tr[rt].r = r, tr[rt].tag = 0;
if (l==r) { tr[rt].c = c[l]; return; }
int mid = l+r >> 1;
build(lson, l, mid), build(rson, mid+1, r);
push_up(rt);
}
void push_down(int rt) {
if (tr[rt].tag) {
tr[lson].c = tr[lson].r-tr[lson].l+1-tr[lson].c;
tr[rson].c = tr[rson].r-tr[rson].l+1-tr[rson].c;
tr[lson].tag ^= 1, tr[rson].tag ^= 1;
tr[rt].tag = 0;
}
}
int query(int rt, int l, int r) {
if (tr[rt].l==l && tr[rt].r==r) return tr[rt].c;
push_down(rt);
int mid = tr[rt].l + tr[rt].r >> 1;
if (r <= mid) return query(lson, l, r);
else if (l > mid) return query(rson, l, r);
else return query(lson, l, mid) + query(rson, mid+1, r);
}
void modify(int rt, int l, int r) {
if (tr[rt].l==l && tr[rt].r==r) {
tr[rt].c = tr[rt].r-tr[rt].l+1-tr[rt].c, tr[rt].tag ^= 1;
return;
}
push_down(rt);
int mid = tr[rt].l+tr[rt].r>>1;
if (r<=mid) modify(lson, l, r);
else if (l > mid) modify(rson, l, r);
else modify(lson, l, mid), modify(rson, mid+1, r);
push_up(rt);
}
int main() {
int n, x;
scanf("%d", &n);
memset(ne, -1, sizeof(ne));
for (int i = 2; i <= n; ++i) {
scanf("%d", &x);
add(x, i);
}
dfs(1);
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
c[l[i]] = x;
}
build(1, 1, n);
int m;
scanf("%d", &m);
char s[5];
while (m--) {
scanf("%s%d", s, &x);
if (s[0]=='g') printf("%d\n", query(1,l[x], r[x]));
else modify(1,l[x], r[x]);
}
return 0;
}
小结
\(D\)和\(E\)这么水...是不是应该以后先看题啊Orz
昨天大半夜构造\(C\)构造了一个多小时...中间还睡着了...还是构造题做得太少。
Codeforces Round #442 Div.2 A B C D E的更多相关文章
- Codeforces Round #442 (Div. 2) Danil and a Part-time Job
http://codeforces.com/contest/877/problem/E 真的菜的不行,自己敲一个模板,到处都是问题.哎 #include <bits/stdc++.h> u ...
- Codeforces Round #442 (Div. 2)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)
题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...
- Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- 【Codeforces Round #442 (Div. 2) D】Olya and Energy Drinks
[链接] 我是链接,点我呀:) [题意] 给一张二维点格图,其中有一些点可以走,一些不可以走,你每次可以走1..k步,问你起点到终点的最短路. [题解] 不能之前访问过那个点就不访问了.->即k ...
- 【Codeforces Round #442 (Div. 2) C】Slava and tanks
[链接] 我是链接,点我呀:) [题意] 有n个位置,每个位置都可能有不定数量的tank; 你每次可以选择一个位置投掷炸弹. 并且,这个位置上的所有tank都会受到你的攻击. 并且失去一点体力. 然后 ...
- 【Codeforces Round #442 (Div. 2) B】Nikita and string
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举中间那一段从哪里开始.哪里结束就好 注意为空的话,就全是a. 用前缀和优化一下. [代码] #include <bits/ ...
- 【Codeforces Round #442 (Div. 2) A】Alex and broken contest
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 注意是所有的名字里面,只出现了其中某一个名字一次. [代码] #include <bits/stdc++.h> usin ...
- Codeforces Round #442 (Div. 2) B题【一道模拟题QAQ】
B. Nikita and string One day Nikita found the string containing letters "a" and "b&qu ...
随机推荐
- python 实现简单语音聊天机器人
'''思路:使用百度的文本转音频API,将结果保存成mp3格式,并用mp3play库播放该文件.''' 1 # -*- coding:utf-8 -*- import sys import reque ...
- 嵌入式linux:通过qemu模拟mini2440开发环境
1 编译安装QEMU 首先下载qemu for mini2440,直接打包下载 http://repo.or.cz/w/qemu/mini2440.git/snapshot/HEAD.tar.gz ...
- JavaScript常用八种继承方案
更新:在常用七种继承方案的基础之上增加了ES6的类继承,所以现在变成八种啦,欢迎加高级前端进阶群一起学习(文末). --- 2018.10.30 1.原型链继承 构造函数.原型和实例之间的关系:每个构 ...
- day 59 MySQL之锁、事务、优化、OLAP、OLTP
MySQL之锁.事务.优化.OLAP.OLTP 本节目录 一 锁的分类及特性 二 表级锁定(MyISAM举例) 三 行级锁定 四 查看死锁.解除锁 五 事务 六 慢日志.执行计划.sql优化 七 ...
- North American Invitational Programming Contest (NAIPC) 2017
(待补) A. Pieces of Parentheses 将括号处理完成后排序,方式参加下面的博客.然后做一遍背包即可. 2018 Multi-University Training Contest ...
- Sliding Window POJ - 2823
Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is m ...
- 菜鸟学Linux - 用户与用户组基础
/etc/passwd: 用户的信息是保存在/etc/passwd下面(早期的时候,用户的密码也是放在该文件中.后来出于安全考虑,将密码放在/etc/shadow中去): /etc/group: 用户 ...
- 2 Model层 -定义模型
1 ORM简介 MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库 ORM是“对象-关系-映射” ...
- 在 Amazon AWS 搭建及部署网站:(二)安装、配置软件,启动网站
现在,我们已经有了一台EC2主机,具备了基本的硬件环境.下面,开始软件环境的配置. 第一步:连接服务器 后面所有的一切,都需要在SSH终端窗口操作.首先,我们需要一个SSH客户端.PuTTY是很常用的 ...
- python 学习分享-实战篇简单的ftp
import socket import os import time import pickle Basedb = os.path.dirname(os.path.dirname(os.path.a ...