Codeforces Round #501 (Div. 3)
A - Points in Segments
题意:implement
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool vis[105];
int ans[105], atop;
void test_case() {
int n, m;
scanf("%d%d", &n, &m);
while(n--) {
int u, v;
scanf("%d%d", &u, &v);
for(int i = u; i <= v; ++i)
vis[i] = 1;
}
for(int i = 1; i <= m; ++i)
if(!vis[i])
ans[++atop] = i;
printf("%d\n", atop);
for(int i = 1; i <= atop; ++i)
printf("%d%c", ans[i], " \n"[i == atop]);
if(atop == 0)
puts("");
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
B - Obtaining the String
题意:给两个字符串s,t,使用冒泡排序从s到达t,求方法。
题解:implement
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char s[105], ss[105], t[105], tt[105];
int ans[10005], atop;
void test_case() {
int n;
scanf("%d%s%s", &n, s + 1, t + 1);
strcpy(ss + 1, s + 1);
strcpy(tt + 1, t + 1);
sort(ss + 1, ss + 1 + n);
sort(tt + 1, tt + 1 + n);
if(strcmp(ss + 1, tt + 1) != 0) {
puts("-1");
return;
}
for(int i = 1; i <= n; ++i) {
while(t[i] != s[i]) {
for(int j = i + 1; j <= n; ++j) {
if(s[j] == t[i]) {
int k = j - 1;
while(t[i] != s[i]) {
ans[++atop] = k;
swap(s[k], s[k + 1]);
--k;
}
break;
}
}
}
}
printf("%d\n", atop);
for(int i = 1; i <= atop; ++i)
printf("%d%c", ans[i], " \n"[i == atop]);
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
C - Songs Compression
题意:有n个数字ai和n个数字bi,花费代价1可以把ai缩小到bi,求缩减总容量小于等于m的最小代价。
题解:implement
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<int> pq;
void test_case() {
int n, m;
scanf("%d%d", &n, &m);
ll sum = 0;
for(int i = 1, a, b; i <= n; ++i) {
scanf("%d%d", &a, &b);
pq.push(a - b);
sum += a;
}
int cnt = 0;
while(pq.size()) {
if(sum <= m)
break;
sum -= pq.top();
++cnt;
pq.pop();
}
if(sum > m)
cnt = -1;
printf("%d\n", cnt);
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
D - Walking Between Houses
题意:有[1,n]号房子,相邻房子距离1,要移动恰好k次,总共恰好s距离,求方法。注意不能原地踏步。
题解:很显然只要是s>=k且s<=k*(n-1)都可以构造,但是因为不能原地踏步就很恶心。先尽可能走最远,直到某次走最远之后会使得s<k,这样就走一步不那么远的直到走完之后s=k,然后反复横跳。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int ans[200005], atop;
void test_case() {
int n, k;
ll s;
scanf("%d%d%lld", &n, &k, &s);
if(s < k || s > (1ll * k * (n - 1))) {
puts("NO");
return;
}
if(s == k) {
puts("YES");
for(int i = 1; i <= k; ++i)
printf("%d%c", 1 + ((i & 1) == 1), " \n"[i == k]);
return;
}
int cur = 1;
while(s - (n - 1) >= (k - 1)) {
s -= n - 1;
k -= 1;
if(cur == 1) {
ans[++atop] = n;
cur = n;
} else {
ans[++atop] = 1;
cur = 1;
}
}
if(k) {
int p = s - (k - 1);
assert(p <= (n - 1));
if(cur == 1) {
ans[++atop] = 1 + p;
cur = 1 + p;
s -= p;
k -= 1;
} else {
ans[++atop] = n - p;
cur = n - p;
s -= p;
k -= 1;
}
}
if(cur == 1) {
for(int i = 1; i <= k; ++i)
ans[++atop] = 1 + ((i & 1) == 1);
} else {
for(int i = 1; i <= k; ++i)
ans[++atop] = cur - ((i & 1) == 1);
}
puts("YES");
ll sum = 0;
ans[0] = 1;
for(int i = 1; i <= atop; ++i) {
printf("%d%c", ans[i], " \n"[i == atop]);
sum += abs(ans[i] - ans[i - 1]);
}
//printf("sum=%lld\n", sum);
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
E1 - Stars Drawing (Easy Edition)
题意:给一个图,用一些十字星把这个图覆盖出来。图<=100*100。
题解:枚举每个中心,然后枚举上下左右拓展的极限,把这个极限覆盖上去,最后得出的图假如和原图不同就-1。
E2 - Stars Drawing (Hard Edition)
题意:图<=1000*1000。把枚举上下左右换成一个很复杂的check,输入一个中心、一个方向和一个长度,返回这段是否完全被覆盖。这个可以用前缀和来实现,所以枚举中心然后二分长度就可以。但是最后答案不能够暴力更新,这个就直接在lr打上差分标记,然后最后扫过来填上去就可以了。
有没有更好的办法?
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
char g[1005][1005];
int prefixl[1005][1005];
int prefixu[1005][1005];
int cntl[1005][1005], cntu[1005][1005];
char ans[1005][1005];
bool checku(int i, int j, int l) {
if(i - l - 1 < 0)
return false;
return (prefixu[i - 1][j] - prefixu[i - l - 1][j]) == l;
}
bool checkl(int i, int j, int l) {
if(j - l - 1 < 0)
return false;
return (prefixl[i][j - 1] - prefixl[i][j - l - 1]) == l;
}
bool checkr(int i, int j, int l) {
if(i + l > n)
return false;
return (prefixu[i + l][j] - prefixu[i][j]) == l;
}
bool checkd(int i, int j, int l) {
if(j + l > m)
return false;
return (prefixl[i][j + l] - prefixl[i][j]) == l;
}
bool check(int i, int j, int l) {
return checku(i, j, l) && checkl(i, j, l) && checkr(i, j, l) && checkd(i, j, l);
}
struct Answer {
int i, j, l;
Answer(int ii, int jj, int ll) {
i = ii, j = jj, l = ll;
}
};
vector<Answer>ans2;
void solve(int i, int j) {
if(i == 1 || j == 1 || i == n || j == m)
return;
if(g[i][j] == '*' && g[i - 1][j] == '*' && g[i + 1][j] == '*' && g[i][j - 1] == '*' && g[i][j + 1] == '*') {
int L = 1, R = min(min(i - 1, n - i), min(j - 1, m - j));
int ans = 0;
while(1) {
int M = L + R >> 1;
if(L == M) {
if(check(i, j, R)) {
ans = R;
break;
}
ans = L;
break;
}
if(check(i, j, M))
L = M;
else
R = M - 1;
}
++cntu[i - ans][j];
--cntu[i + ans + 1][j];
++cntl[i][j - ans];
--cntl[i][j + ans + 1];
ans2.push_back(Answer(i, j, ans));
}
return;
}
void test_case() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%s", g[i] + 1);
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j)
prefixl[i][j] = prefixl[i][j - 1] + (g[i][j] == '*');
}
for(int j = 1; j <= m; ++j) {
for(int i = 1; i <= n; ++i)
prefixu[i][j] = prefixu[i - 1][j] + (g[i][j] == '*');
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j)
solve(i, j);
}
memset(ans, '.', sizeof(ans));
for(int i = 1; i <= n; ++i) {
int cur = 0;
for(int j = 1; j <= m; ++j) {
cur += cntl[i][j];
if(cur)
ans[i][j] = '*';
}
}
for(int j = 1; j <= m; ++j) {
int cur = 0;
for(int i = 1; i <= n; ++i) {
cur += cntu[i][j];
if(cur)
ans[i][j] = '*';
if(ans[i][j] != g[i][j]) {
puts("-1");
return;
}
}
}
printf("%d\n", (int)ans2.size());
for(auto i : ans2)
printf("%d %d %d\n", i.i, i.j, i.l);
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
事实上并不需要二分,可以dp转移出四个方向上的最远值。然后直接取min。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
char g[1005][1005];
short u[1005][1005];
short d[1005][1005];
short l[1005][1005];
short r[1005][1005];
short cntu[1005][1005];
short cntl[1005][1005];
char ans[1005][1005];
struct Answer {
int i, j, l;
Answer(int ii, int jj, int ll) {
i = ii, j = jj, l = ll;
}
};
vector<Answer>ans2;
void solve(int i, int j) {
int len = min(min(u[i][j], d[i][j]), min(l[i][j], r[i][j]));
if(len <= 1)
return;
len -= 1;
++cntu[i - len][j];
--cntu[i + len + 1][j];
++cntl[i][j - len];
--cntl[i][j + len + 1];
ans2.push_back(Answer(i, j, len));
}
void test_case() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%s", g[i] + 1);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
u[i][j] = (g[i][j] == '*') ? u[i - 1][j] + 1 : 0;
l[i][j] = (g[i][j] == '*') ? l[i][j - 1] + 1 : 0;
}
}
for(int i = n; i >= 1; --i) {
for(int j = m; j >= 1; --j) {
d[i][j] = (g[i][j] == '*') ? d[i + 1][j] + 1 : 0;
r[i][j] = (g[i][j] == '*') ? r[i][j + 1] + 1 : 0;
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j)
solve(i, j);
}
memset(ans, '.', sizeof(ans));
for(int i = 1; i <= n; ++i) {
int cur = 0;
for(int j = 1; j <= m; ++j) {
cur += cntl[i][j];
if(cur)
ans[i][j] = '*';
}
}
for(int j = 1; j <= m; ++j) {
int cur = 0;
for(int i = 1; i <= n; ++i) {
cur += cntu[i][j];
if(cur)
ans[i][j] = '*';
if(ans[i][j] != g[i][j]) {
puts("-1");
return;
}
}
}
printf("%d\n", (int)ans2.size());
for(auto i : ans2)
printf("%d %d %d\n", i.i, i.j, i.l);
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
F - Bracket Substring
题意:有个不一定合法的括号串s,求长度为2n的串中有多少种是包含n为子串且合法的。
题解:换句话说就是在左右加一个n个使得它合法,问有多少种。看起来像是dp。设dp[i][j][k]为已经有总共i长度的串,其中现在以s的第j位结尾,左括号比右括号多k个的合法方案数,则答案为dp[2n][l][0]。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
char s[205];
ll dp[205][205][205];
void test_case() {
int n;
scanf("%d%s", &n, s + 1);
int l = strlen(s + 1);
dp[0][0][0] = 1;
for(int i = 1; i <= 2 * n; ++i) {
//没有进入s串,直接转移
for(int k = 0; k <= i; ++k)
dp[i][0][k] = (k >= 1 ? dp[i - 1][0][k - 1] : 0) + dp[i - 1][0][k + 1];
//开始进入s串/已经进入s串
for(int j = 1; j <= min(i, l); ++j) {
if(s[j] == '(') {
for(int k = 0; k <= i; ++k)
dp[i][j][k] = (k >= 1 ? dp[i - 1][j - 1][k - 1] : 0);
} else {
for(int k = 0; k <= i; ++k)
dp[i][j][k] = dp[i - 1][j - 1][k + 1];
}
}
//结束进入s串
if(i > l && l) {
for(int k = 0; k <= i; ++k)
dp[i][l][k] += (k >= 1 ? dp[i - 1][l][k - 1] : 0) + dp[i - 1][l][k + 1];
}
for(int j = 0; j <= min(i, l); ++j) {
for(int k = 0; k <= i; ++k) {
dp[i][j][k] %= MOD;
printf("dp[%d][%d][%d]=%lld\n", i, j, k, dp[i][j][k]);
}
}
printf("\n");
}
printf("%lld\n", dp[2 * n][l][0] % MOD);
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t = 1;
for(int ti = 1; ti <= t; ++ti) {
//printf("Case #%d: ", ti);
test_case();
}
}
这样会重复,比如
2
()
答案应该是2,但是上面这样会输出3。
解决的办法要利用字符串里面的KMP算法的next数组,得先放一下。
Codeforces Round #501 (Div. 3)的更多相关文章
- Codeforces Round #501 (Div. 3) F. Bracket Substring
题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...
- Codeforces Round #501 (Div. 3) D. Walking Between Houses
题目链接 题意:给你三个数n,k,sn,k,sn,k,s,让你构造一个长度为k的数列,使得相邻两项差值的绝对值之和为sss, ∑i=1n∣a[i]−a[i−1]∣,a[0]=1\sum_{i=1}^n ...
- Codeforces Round #501 (Div. 3) 1015D Walking Between Houses
D. Walking Between Houses time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- Codeforces Round #501 (Div. 3) 1015A Points in Segments (前缀和)
A. Points in Segments time limit per test 1 second memory limit per test 256 megabytes input standar ...
- 【Codeforces Round #501 (Div. 3)】
A:https://www.cnblogs.com/myx12345/p/9842904.html B:https://www.cnblogs.com/myx12345/p/9842964.html ...
- Codeforces Round #501 (Div. 3) D. Walking Between Houses (思维,构造)
题意:一共有\(n\)个房子,你需要访问\(k\)次,每次访问的距离是\(|x-y|\),每次都不能停留,问是否能使访问的总距离为\(s\),若能,输出\(YES\)和每次访问的房屋,反正输出\(NO ...
- Codeforces Round #501 (Div. 3) B. Obtaining the String (思维,字符串)
题意:有两个字符串\(S\)和\(T\),判断\(T\)是否能由\(S\)通过交换某位置的相邻字符得到,如果满足,输出交换次数及每次交换的位置,否则输出\(-1\). 题解:首先判断不满足的情况,只有 ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
随机推荐
- [转载] jmeter Bean Shell的使用
Jmeter有哪些Bean Shell 定时器: BeanShell Timer 前置处理器:BeanShell PreProcessor 采样器: BeanShell Sampler 后置处理器:B ...
- javascript 之 命名空间
注意点: 1/IIFE是现代js框架最主要的基础设施,保证变量不被污染. 2/基本上我们把命名空间等同于框架的名字. 内容 一.简单的命名空间 <input type="button& ...
- python 内置函数和匿名函数
内置函数 截止到python版本3.6.2,现在python一共为我们提供了68个内置函数. Built-in Functions abs() dict() help() min() ...
- 【转载】C#使用Split函数根据特定分隔符分割字符串
在C#程序开发过程中,很多时候可能需要将字符串根据特定的分割字符分割成字符或者List集合,例如根据逗号将字符串分割为数组,或者根据竖线将字符串分割成数组,C#中提供了Split()函数来快速将字符串 ...
- MM-发票校验与收货的差异处理
SAP FI-财务发票校验修改金额后没有进入差异科目问题:公司新建物料采购订单,在MM科目自动确定配置完成后,做发票校验时,修改金额没修改数量时,差异进入了原材料科目 换采购订单继续测试时,修改金额没 ...
- flutter常见编译运行等奇怪问题的汇总汇(l转)
1. flutter ios 卡死在闪屏页:解决办法: 1) flutter doctor 2) flutter clean 3) flutter build ios --release 4) Arc ...
- shell 三剑客之 sed pattern 详解
sed 基础介绍 语法格式 sed 处理过程 sed 选项 cat sed.txt '-p' 打印输出 ,默认输出两次,流输出一次,源文件输出一次 sed 'p' sed.txt -n 只显示处理的 ...
- 一个让Java事半功倍的反射库
在Java和Android中,我们常常会使用反射来达到一些兼容的目的.Java原生提供的反射很是麻烦,使用起来很是不方便.比如我们想要调UserManager的静态方法get,使用原生的实现如下 tr ...
- OAuth2在微服务架构中的应用
首先是为什么要在微服务场景使用OAuth2,这是因为使用了OAuth2后,就能向第三方系统提供授权. 其次是如何使用,见下图: 在微服务架构中使用OAuth2,有几个问题需要我们思考: 1. toke ...
- 聊天程序——基于Socket、Thread (二)
聊天程序简述 1.目的:主要是为了阐述Socket,以及应用多线程,本文侧重Socket相关网路编程的阐述.如果您对多线程不了解,大家可以看下我的上一篇博文浅解多线程 . 2.功能:此聊天程序功能实现 ...