地址:http://codeforces.com/contest/890
A. ACM ICPC
给你6个数字,能否凑成两组,和相等。
#include <bits/stdc++.h>
using namespace std;
int a[6], sum = 0;
bool solve()
{
do
{
int cnt = 0;
for(int i = 0; i < 3; i++) cnt+=a[i];
if(cnt * 2 == sum) return true;
}while(next_permutation(a, a + 6));
return false;
}
int main()
{
for(int i = 0; i < 6; i++) scanf("%d", &a[i]), sum += a[i];
sort(a, a + 6);
if(solve()) puts("YES");
else puts("NO");
return 0;
}
B. Vlad and Cafes
给你十万个数,问你从后往前数最早的一个 使得n个数字里面所有数字都出现过至少一次的 数字是几。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn];
set<int>s;
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
s.insert(a[i]);
}
int m = s.size();
s.clear();
for(int i = n - 1; i >= 0; i --)
{
s.insert(a[i]);
if(s.size() == m)
{
printf("%d\n", a[i]);
break;
}
}
return 0;
}
C. Petya and Catacombs(贪心)
给你十万个时间点,每个时间点i出现在一个房间里。如果是出现在曾经去过的房间里,则写下上一次到达这个房间的时间点,否则随机写一个小于当前时间i的数字。问你至少需要去几个不同的房间能满足给出的时间点序列。
思路:贪心一下,每次尽量去去过的房间,不够用的时候加一个就行了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn];
map<int, int>ma;
int main()
{
int n;
scanf("%d", &n);
int cnt = 0;
for(int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
if(ma[x])
{
ma[x] = 0;
ma[i] = 1;
}
else if(ma[x] == 0)
{
ma[i] = 1;
cnt++;
}
}
printf("%d\n", cnt);
return 0;
}
D. Restoration of string(拓扑排序)
给出十万个字符串,总长度不超过十万,要求构造一个字符串,使得所有给出的字符串在这个串当中都是出现次数最多子串。输出长度最短的答案。如果有多个答案,输出字典序最小的。
思路:
把每个给出的字符串中,相邻的两个字符连上一条有向边。
首先我们要知道,如果有解,那么这个解应该是若干条链贪心加和。所以出现环则无解。
其次每个点的出入度最大只能为1,否则无法满足题意。
最后要注意处理单个字符的情况。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
char str[maxn];
int vis[maxn], out[maxn], in[maxn], input[maxn];
vector<string>vec;
vector<int>G[maxn];
string temp;
int ok;
void dfs(int cur)
{
if(ok == 0) return ;
vis[cur] = 1;
temp += 'a' + cur;
for(auto v : G[cur])
{
if(vis[v]) ok = 0;
dfs(v);
}
}
bool solve()
{
for(int i = 0; i < 26; i++)
{
out[i] += G[i].size();
for(auto o : G[i]) in[o]++;
}
for(int i = 0; i < 26; i++)
{
if(in[i] > 1 || out[i] > 1) return false;
}
for(int i = 0; i < 26; i++)
{
ok = 1;
temp = "";
if(in[i] == 0 && out[i]) dfs(i);
vec.push_back(temp);
if(ok == 0) return false;
}
for(int i = 0; i < 26; i++)
{
if(vis[i] == 0 && in[i]) return false;
if(vis[i] == 0 && input[i])
{
string t = "";
t += ('a' + i);
vec.push_back(t);
}
}
sort(vec.begin(), vec.end());
string ans = "";
for(auto o : vec) ans += o;
cout << ans << endl;
return true;
}
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s", str);
int len = strlen(str);
if(len == 1) input[str[0] - 'a'] = 1;
else
{
for(int j = 0; j < len - 1; j++)
{
int lb = str[j] - 'a', rb = str[j + 1] - 'a';
G[lb].push_back(rb);
}
}
}
for(int i = 0; i < 26; i++)
{
sort(G[i].begin(), G[i].end());
G[i].resize(unique(G[i].begin(), G[i].end()) - G[i].begin());
}
if(solve() == 0) puts("NO");
return 0;
}