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. 问题:Could not install packages due to an EnvironmentError: [Errno 13] Permission denied:

    1.安装django 执行pip3 install --user django 2.解决方法:加--user   执行pip3 install --user django

  2. Spring的datasource配置详解【转】

    一句话,Spring对Hibernate的整合,是在applicationContext.xml中配置sessionFactory来实现的,其中sessionFactory中要装配dataSource ...

  3. MongDB之各种查询操作

    接口IMongDaoFind: package com.net.test.mongdb.dao; public interface IMongDaoFind { public void findUse ...

  4. C语言实例解析精粹学习笔记——44(冒泡排序)

    冒泡排序,从序列的最后一个元素与前一个元素比较大小,如果R[n-1]>R[n]则交换两个元素的位置(R[0]作为临时存放区)将最小的数据交换到R[1],第二次循环将第二小的数交换到R[2].通过 ...

  5. A1025 PAT Ranking (25)(25 分)

    A1025 PAT Ranking (25)(25 分) Programming Ability Test (PAT) is organized by the College of Computer ...

  6. 快速排序,对于相同元素的优化,c++

    #include<iostream>using namespace std; void middl(int &p,int &q,int &r)//找枢轴,然后把枢轴 ...

  7. Apache虚拟主机测试

    一.虚拟机主机简介 部署多个站点,每个站点,希望用不同的域名和站点目录,或者是不同的端口,或不同的ip,就需要虚拟主机功能.简单的说一个http服务要配置多个站点,就需要虚拟主机.(一句话一个http ...

  8. James Bach Rapid Test的感受

    前阶段拜读过James大神的快速测试,英文水平有限,阅读起来有点吃力,虽然想亲自参加大神的培训,一直没有机会,不过阿里牛人参加大神的培训,并总结的不错,现在谈谈自己的感想和看法. 进入测试行业不少年了 ...

  9. 【小程序入门集锦】19,微信小程序个人帐号申请

    个人账号与企业帐号相比,缺少支付等功能,与个人订阅号类似.   小程序开放个人开发者申请注册,个人用户可访问微信公众平台,扫码验证个人身份后即可完成小程序帐号申请并进行代码开发.   下面我们就来说说 ...

  10. React基础(Diff算法,属性和状态)

    1.React的背景原理 (1)React Diff算法流程 (2)React虚拟DOM机制 React引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DO ...