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. 先往偶数格子中扔炸弹时,偶数格子中的所有坦克都跑到了奇数格子中;

    此时,只有奇数格子中有坦克,且其中的坦克分为两类:血量为\(1\),血量为\(2\)

  2. 再往奇数格子中扔炸弹,奇数格子中 1) 血量为\(1\)的坦克全都死了; 2) 血量为\(2\)的坦克都跑到了偶数格子中;

    此时,只有偶数格子中有坦克,且其中的坦克只有一类:血量为\(1\)

  3. 最后往偶数格子中扔坦克,全都死了

至于为什么是\(偶\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\). 有两种操作,

  1. \(get\ v\):询问以\(v\)为根的子树中有多少个点的值为\(1\);
  2. \(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的更多相关文章

  1. Codeforces Round #442 (Div. 2) Danil and a Part-time Job

    http://codeforces.com/contest/877/problem/E 真的菜的不行,自己敲一个模板,到处都是问题.哎 #include <bits/stdc++.h> u ...

  2. Codeforces Round #442 (Div. 2)

    A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  3. 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序加上一个线 ...

  4. 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 ...

  5. 【Codeforces Round #442 (Div. 2) D】Olya and Energy Drinks

    [链接] 我是链接,点我呀:) [题意] 给一张二维点格图,其中有一些点可以走,一些不可以走,你每次可以走1..k步,问你起点到终点的最短路. [题解] 不能之前访问过那个点就不访问了.->即k ...

  6. 【Codeforces Round #442 (Div. 2) C】Slava and tanks

    [链接] 我是链接,点我呀:) [题意] 有n个位置,每个位置都可能有不定数量的tank; 你每次可以选择一个位置投掷炸弹. 并且,这个位置上的所有tank都会受到你的攻击. 并且失去一点体力. 然后 ...

  7. 【Codeforces Round #442 (Div. 2) B】Nikita and string

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举中间那一段从哪里开始.哪里结束就好 注意为空的话,就全是a. 用前缀和优化一下. [代码] #include <bits/ ...

  8. 【Codeforces Round #442 (Div. 2) A】Alex and broken contest

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 注意是所有的名字里面,只出现了其中某一个名字一次. [代码] #include <bits/stdc++.h> usin ...

  9. Codeforces Round #442 (Div. 2) B题【一道模拟题QAQ】

    B. Nikita and string One day Nikita found the string containing letters "a" and "b&qu ...

随机推荐

  1. 用户和用户组以及 Linux 权限管理

    1.从 /etc/passwd 说起 前面的基本命令学习中,我们介绍了使用 passwd 命令可以修改用户密码.对于操作系统来说,用户名和密码是存放在哪里的呢?我们都知道一个站点的用户名和密码是存放在 ...

  2. 初学puppet

    初学puppet puppet是什么? puppet是一个开源的软件自动化配置和部署工具,很多大型IT公司均在使用puppet对集群中的软件进行管理和部署. Puppet简介 Puppet的目录是让管 ...

  3. 使用IP访问本地网站缓慢解决方法

    运行环境: win7 64位 apache2.4 php-5.6.37 最近由于业务需要,需要使用php5.6版本,所以配套升级了apache到2.4,但升级以后,发现用公司内网IP访问网站非常非常慢 ...

  4. JavaScript 资源大全中文版

    我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-javascript 是 sorrycc 发起维护的 JS 资源列表,内容包括:包管理器.加 ...

  5. 数据结构-哈夫曼(Huffman)

    #include <iostream> #include <cstdio> #include <malloc.h> #define LIST_INIT_SIZE 1 ...

  6. 04构建之法读书笔记——IT行业的创新

    IT行业的创新: 1.创新的迷思: 灵光一闪现,伟大的创新就紧随其后:大家都喜欢创新:好的想法会赢:创新者都是一马当先:要成为领域的专家,才能创新:技术的创新是关键:成功的团队更能创新 2.创新的时机 ...

  7. python字符串处理方法

    一.combine & duplicate 字符串结合和复制 字符和字符串可以用来相加来组合成一个字符串输出: 字符或字符串复制输出. 二.Extract &Slice 字符串提取和切 ...

  8. 全球征集-如何实现回文SQL的查询

    有个表,以下是创建的SQL: CREATE TABLE [dbo].[SysName]( ,) NOT NULL, ) COLLATE Chinese_PRC_CI_AS NULL, ) COLLAT ...

  9. BZOJ 1222: [HNOI2001]产品加工

    F[i]表示第一个机器用了i的时间,第二个机器的最小时间 转移即可 #include<cstdio> #include<algorithm> using namespace s ...

  10. [网站公告]11月26日00:00-04:00阿里云RDS升级

    大家好,11月26号00:00-04:00(今天夜里),阿里云将对我们所用的SQL Server RDS实例所在的物理主机做升级操作(目前博客园整站运行于阿里云上),升级期间RDS实例会有2次闪断,每 ...