文章目录
- CF EDU4
- [A. The Text Splitting](http://codeforces.com/contest/612/problem/A)
- [B. HDD is Outdated Technology](http://codeforces.com/contest/612/problem/B)
- [C. Replace To Make Regular Bracket Sequence](http://codeforces.com/contest/612/problem/C)
- 思路
- [D. The Union of k-Segments](http://codeforces.com/contest/612/problem/D)
CF EDU4
A. The Text Splitting
思路
首先总串的长度是固定的, 设为n, 那么我们只要找到这样一个条件:
∃
x
,
y
∈
N
,
q
x
+
p
y
=
n
\exists x, y \in N, \quad qx + py = n
∃x,y∈N,qx+py=n那么其实我们直接可以暴力枚举x, 判断y是否符合即可。
得到x, y之后, 无脑输出。特判如果x和y都无法取值的话, 输出-1
代码
#include<bits/stdc++.h>
using namespace std;
int n, p, q;
string s;
int ansp = 0, ansq = 0;
int main()
{
cin >> n >> p >> q;
cin >> s;
int n = s.size();
for(int cntp = 0; cntp * p <= n; cntp++)
{
int total = cntp * p;
int rest = n - total;
// cout << cntp << " " << total << " " << n << " " << rest << endl;
if(rest % q == 0)
{
ansp = cntp;
ansq = rest / q;
break;
}
}
if(ansp == ansq && ansp == 0)
{
cout << -1 << endl;
}
else
{
cout << ansp + ansq << endl;
int now = 0;
while(ansp--)
{
for(int i = now; i < now + p; i++)
{
cout << s[i];
}
now += p;
cout << endl;
}
while(ansq--)
{
for(int i = now; i < now + q; i++)
{
cout << s[i];
}
now += q;
cout << endl;
}
// cout << now << endl;
}
return 0;
}
大佬直接双重枚举x, y。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>
using namespace std;
const int N = 111;
int n, p, q;
string s;
int main()
{
cin >> n >> p >> q;
cin >> s;
for (int x = 0; x <= n; x++)
for (int y = 0; y <= n; y++)
{
if (x * p + y * q != n) continue;
cout << x + y << endl;
int it = 0;
for (int i = 0; i < x; i++)
{
cout << s.substr(it, p) << endl;
it += p;
}
for (int i = 0; i < y; i++)
{
cout << s.substr(it, q) << endl;
it += q;
}
return 0;
}
cout << "-1\n";
return 0;
}
B. HDD is Outdated Technology
思路
将i与fi换维, 表示第fi个扇区对应的位置在哪。这样我们只需要把fi从1遍历到n并计算 ∣ a − b ∣ |a - b| ∣a−b∣即可
代码
#include<bits/stdc++.h>
using namespace std;
int fp[200010];
int n;
int f[200010];
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> f[i];
fp[f[i]] = i;
}
long long ans = 0;
for(int i = 2; i <= n; i++)
{
ans += (long long)abs(fp[i] - fp[i-1]);
}
cout << ans << endl;
return 0;
}
C. Replace To Make Regular Bracket Sequence
思路
和括号匹配很像, 开一个栈, 放左括号, 从后往前遍历, 如果当前位置为右括号, 且与栈顶为同一种左括号, 那么弹栈, 如果不同, 那么必须替换一个括号才能保证合法。如果为空, 那么绝对不合法。
遍历完后如果栈不空 ,同样不合法
注:不合法就是不是RBS
代码
#include<bits/stdc++.h>
using namespace std;
string s;
stack<char> st;
bool flag = true;
int ans = 0;
int main()
{
cin >> s;
for(int i = 0; i < s.size(); i++)
{
//cout << s[i] << " " << st.top() << endl;
if(s[i] == '(' || s[i] == '{' || s[i] == '<' || s[i] == '[')
{
st.push(s[i]);
continue;
}
else if(s[i] == ')')
{
if(st.empty())
{
flag = false;
break;
}
if(st.top() == '(')
{
st.pop();
continue;
}
else
{
ans++;
st.pop();
}
}
else if(s[i] == ']')
{
if(st.empty())
{
flag = false;
break;
}
if(st.top() == '[')
{
st.pop();
continue;
}
else
{
ans++;
st.pop();
}
}
else if(s[i] == '}')
{
if(st.empty())
{
flag = false;
break;
}
if(st.top() == '{')
{
st.pop();
continue;
}
else
{
ans++;
st.pop();
}
}
else if(s[i] == '>')
{
if(st.empty())
{
flag = false;
break;
}
if(st.top() == '<')
{
st.pop();
continue;
}
else
{
ans++;
st.pop();
}
}
}
if(flag == 0 || !st.empty())
{
printf("Impossible");
}
else
{
cout << ans << endl;
}
return 0;
}
大佬开了一个map将左右括号对应
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <map>
#include <cstring>
using namespace std;
const int N = (int)1e6 + 100;
map<char, char> m;
int n;
char s[N];
char st[N];
int sz;
bool isOpening(char c)
{
return m.count(c) > 0;
}
bool arePair(char c1, char c2)
{
return m[c1] == c2;
}
int main()
{
m['('] = ')';
m['['] = ']';
m['<'] = '>';
m['{'] = '}';
scanf(" %s ", s);
n = strlen(s);
sz = 0;
int ans = 0;
for (int i = 0; i < n; i++)
{
if (isOpening(s[i]))
st[sz++] = s[i];
else
{
if (sz == 0)
{
printf("Impossible\n");
return 0;
}
sz--;
if (!arePair(st[sz], s[i])) ans++;
}
}
if (sz == 0)
printf("%d\n", ans);
else
printf("Impossible\n");
return 0;
}
D. The Union of k-Segments
这个题我没有真正的A掉, TLE了, 所以我先说一下我的想法
思路
我的想法就是正这扫一遍, 记录当前这个点有几个线段覆盖, 记录方式:遇到左端点+1,右端点-1。
那么如果遇到一个左端点加一后大约等于k的话, 我们就开始统计答案, 当遇到右端点-1又小于k时, 我们结束统计答案
TLE 代码
#include<bits/stdc++.h>
using namespace std;
int n, k;
struct seg
{
int d, type;
}s[1000010 * 2];
int cnt = 0;
bool cmp(seg a, seg b)
{
if(a.d == b.d)
{
return a.type < b.type;
}
return a.d <= b.d;
}
seg ans[1000010 * 2];
int cnta;
int main()
{
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
s[++cnt].d = x;
s[cnt].type = 0;
s[++cnt].d = y;
s[cnt].type = 1;
}
sort(s+1, s+1+cnt, cmp);
int now = 0;
bool flag = false;
for(int i = 1; i <= cnt; i++)
{
if(s[i].type == 0)
{
now++;
if(now >= k && !flag)
{
ans[++cnta].d = s[i].d;
flag = true;
}
}
else if(s[i].type == 1)
{
now--;
if(now < k && flag)
{
ans[cnta].type = s[i].d;
flag = false;
}
}
}
cout << cnta << endl;
for(int i = 1; i <= cnta; i++)
{
cout << ans[i].d << " " << ans[i].type << endl;
}
return 0;
}
大佬蒙逼做法
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Event
{
int type;
int x;
Event() : type(), x() {}
Event(int _type, int _x) : type(_type), x(_x) {}
bool operator < (const Event &e) const
{
if (x != e.x) return x < e.x;
return type < e.type;
}
};
const int INF = (int)1e9 + 100;
const int N = (int)2e6 + 300;
int n;
int ans[N][2];
Event ev[N];
int ansSz = 0;
int k;
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++)
{
int l, r;
scanf("%d%d", &l, &r);
ev[2 * i] = Event(0, l);
ev[2 * i + 1] = Event(1, r);
}
n *= 2;
sort(ev, ev + n);
int L = INF;
for (int i = 0; i < n; i++)
{
if (ev[i].type == 0)
{
k--;
if (k == 0)
L = ev[i].x;
}
else
{
k++;
if (k == 1)
{
ans[ansSz][0] = L;
ans[ansSz][1] = ev[i].x;
ansSz++;
L = INF;
}
}
}
printf("%d\n", ansSz);
for (int i = 0; i < ansSz; i++)
printf("%d %d\n", ans[i][0], ans[i][1]);
return 0;
}