A:Diverse Strings
题意
给定n个字符串,判断每个字符串是否恰好由连续且不重复的字母组成。
关键词
字符串、排序、去重。
思路
对字符串去重再排序,如果处理后的长度没变且最后一个字符与第一个字符恰好相差len-1(字符串长度),则输出YES,否则输出NO。
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 1000056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
bool tag[MAXN];
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
int n;
cin>>n;
for (int i = 0; i < n; ++i)
{
string s;
cin>>s;
memset(tag, 0, sizeof(tag));
bool ans = 1;
sort(s.begin(),s.end());
int r = unique(s.begin(),s.end())-s.begin();
if (r == s.length()&& s.back()-s[0] == s.length()-1)
ans = 1;
else ans = 0;
if(ans)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}
B:Parity Alternated Deletions
题意
给n个正整数,在其中交替删除奇偶数,再无法继续删除后,求剩下的数之和最小是多少。
关键词
奇偶、排序。
思路
把奇数和偶数分开储存并排序,算出其数量之差cnt,在数量多那个序列中取最小的前cnt-1个数之和。
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 1000056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
int arr[MAXN];
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
int n;
cin >> n;
int x = 0, y = 0;
int xx = INT_MAX, yy = INT_MAX;
vector<int> xxx,yyy;
int ans = 0;
for (int i = 0; i < n; ++i)
{
cin >> arr[i];
if (arr[i] & 1)
{
x++;
xx = min(xx, arr[i]);
xxx.push_back(arr[i]);
} else
{
y++;
yy = min(yy, arr[i]);
yyy.push_back(arr[i]);
}
}
int cnt = abs(x - y);
if (cnt <= 1)
ans = 0;
else
{
cnt -= 1;
if(x>y)
{
sort(xxx.begin(), xxx.end());
ans = accumulate(xxx.begin(), xxx.begin()+cnt, 0);
} else{
sort(yyy.begin(), yyy.end());
ans = accumulate(yyy.begin(), yyy.begin()+cnt, 0);
}
}
cout << ans << endl;
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}
C:Two Shuffled Sequences
题意
给n个数,如果能拆分成一个绝对升序(不含相等元素)的序列和一个绝对降序的序列,则输出YES和这两个序列,否则输出NO。
关键词
排序,去重。
思路
开两个标记数组标记是否在升序、降序序列中出现过,如果没在升序序列出现,则加入升序序列,否则再判断有没有存在于降序序列中,如果没存在,则加入降序序列,否则不放入这两个序列。
比较两个序列中元素数量之和是否等于n,等于,则有解,对这两个序列按照升序、降序排序后输出,否则无解。
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 1000056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
int arr[MAXN];
int vis[MAXN] = {0};
int vis2[MAXN] = {0};
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
int n;
cin >> n;
vector<int> a, b;
bool tag = 1;
for (int i = 0; i < n; ++i)
{
cin >> arr[i];
if (!vis[arr[i]])
{
a.push_back(arr[i]);
vis[arr[i]] = 1;
} else if (!vis2[arr[i]])
{
b.push_back(arr[i]);
vis2[arr[i]] = 1;
}
}
if (a.size() + b.size() != n)
tag = 0;
if (tag)
{
cout << "YES" << endl;
sort(a.begin(), a.end());
cout << a.size() << endl;
for (int i = 0; i < a.size(); ++i)
{
if (i)
cout << " ";
cout << a[i];
}
cout << endl;
cout << b.size() << endl;
sort(b.begin(), b.end(), greater<int>());
for (int i = 0; i < b.size(); ++i)
{
if (i)
cout << " ";
cout << b[i];
}
cout << endl;
} else
cout << "NO" << endl;
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}
D:Equalize Them All
题意
给定包含n个数的序列,每一次操作可以把一个数变成相邻的数,问最少需要多少次操作才能把这个序列变成同一个数,输出操作步骤。
关键词
众数、搜索、贪心。
思路
找到序列中的众数(出现次数最多的数)。
假设众数有k个,则要将所有数字都变成众数需要的操作数量最少,为n-k次:每次都将众数左右两边的数变成众数即可,类似于BFS。
将这些众数的位置存入队列中,用类似于BFS的方式去处理并记录操作。
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 1000056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
int arr[MAXN];
int vis[MAXN] = {0};
int cnt[MAXN] = {0};
int tot = 0;
int ans[MAXN][3];
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
int n;
cin >> n;
int m_cnt = 0;
int m_num = 0;
for (int i = 0; i < n; ++i)
{
cin >> arr[i];
cnt[arr[i]]++;
if (cnt[arr[i]] > m_cnt)
{
m_cnt = cnt[arr[i]];
m_num = arr[i];
}
}
queue<int> q;
for (int i = 0; i < n; ++i)
{
if (arr[i] == m_num)
{
q.push(i);
vis[i] = 1;
}
}
while (!q.empty())
{
int cur = q.front();
q.pop();
if (cur > 0 && !vis[cur - 1] )
{
q.push(cur - 1);
ans[tot][0] = arr[cur - 1] < m_num ? 1 : 2;
ans[tot][1] = cur - 1;
ans[tot++][2] = cur;
vis[cur-1] = 1;
}
if (cur < n - 1 && !vis[cur + 1])
{
q.push(cur + 1);
ans[tot][0] = arr[cur + 1] < m_num ? 1 : 2;
ans[tot][1] = cur + 1;
ans[tot++][2] = cur;
vis[cur+1] = 1;
}
}
cout<<tot<<endl;
for (int i = 0; i <tot; ++i)
{
printf("%d %d %d\n",ans[i][0], ans[i][1]+1 ,1+ans[i][2]);
}
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}
E:Median String
题意
给一个整数n,给出2个长度为n的字符串,求按照字典序在这两个字符串之间的字符串。
关键词
26进制、字典序、数论
思路
先做加法,再求平均。
设连个字符串为a、b。
数a可表示为:a0⋅261+a2⋅26n-2+……+an-1⋅260,b同理。
加法,从最低位开始:
相加:sumi-1+=ai-1+bi-1
进位:sumi-2+=sumi-1/26
求余:sumi-1%=26
除2,从最高位开始:
模二:r = sumi%2
除二:sumi/=2
退位:sumi+1+=r*26
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 200056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
int sum[MAXN] = {0};
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
int n;
cin >> n;
string s1, s2;
cin >> s1 >> s2;
for (int i = n; i >= 0; --i)
{
int t = 0;
if(i>0)
t=(s1[i-1] - 'a') + (s2[i-1] - 'a');
sum[i] += t;
if(i)
{
sum[i-1] += sum[i] / 26;
sum[i] %= 26;
}
}
for (int i = 0; i <= n; ++i)
{
int r = sum[i] % 2;
sum[i] /= 2;
if (i < n)
sum[i + 1] += 26 * r;
}
for (int i = 0; i <= n; ++i)
{
if (i == 0 && sum[i] == 0)
continue;
else
cout << (char) (sum[i] + 'a');
}
cout << endl;
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}
F:Graph Without Long Directed Paths
题意
给一个由n个点、m条边组成的无图,问是否能给边加上方向,让整个图不存在长度超过一的路径。
关键词
DFS、图染色
思路
要没有长度超过1的路径,在这个图中只有2种点:一种入度为0、一种出度为0,且同一种点不能相邻出现。
就是一个图染色问题,能否用两种颜色对图染色。直接DFS即可。
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 1000056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
int n, m;
int vis[MAXN] = {0};
vector<Pair> G[MAXN];
int in[MAXN];
int ans[MAXN] = {0};
int tag = 1;
vector<Pair> edges;
void addedge (int a, int b, int i)
{
G[a].pb(Pair(b, i));
G[b].pb(Pair(a, i));
edges.pb(Pair(a, b));
}
void dfs (int u, int _in)
{
if (!tag)
return;
vis[u] = 1;
in[u] = _in;
for (int i = 0; i < G[u].size(); ++i)
{
int v = G[u][i].first;
int index = G[u][i].second;
if (in[v] == -1)
{
dfs(v, 1 - _in);
} else if (in[u] == in[v])
{
tag = 0;
return;
}
}
}
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
cin >> n >> m;
memset(in, -1, sizeof(in));
for (int i = 0; i < m; ++i)
{
int a, b;
cin >> a >> b;
addedge(a, b, i);
}
dfs(1, 0);
if (tag)
{
cout << "YES" << endl;
for (int i = 0; i < m; ++i)
{
int u = edges[i].first;
int v = edges[i].second;
cout << (in[u]<in[v]);
}
cout << endl;
} else
{
cout << "NO" << endl;
}
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}
G:Two Merged Sequences
题意
这道题题意和C题类似,区别就是,在C题中,可以对数组中的数重新排序,而在这题中,要求保持数组中给的顺序。
关键词
贪心、DP
思路
贪心思路:
如图,贪心的思路,就是让升序序列与降序序列之间,能插入数的范围尽可能大,即能保证尽可能多的数能被插入到两个序列之中,可以求出最优解。
假设维护一个升序序列、一个降序序列,对于当前的待处理的数x以及下一个数y,使用贪心思想分析以下几种情况:
- x即能加入升序序列,又能加入降序序列:如果y>x,则把x加入降序序列,那么y就只能加入升序序列,此时的情况,显然比把x加入升序序列更糟糕。故y>x的情况下,把x加入升序序列,否则加入降序序列。如果x为最后一个元素,则加入哪个序列都行。
- x只能加入其中一个序列:直接加入。
- 两个序列都无法加入:此时无解。
代码
#include <bits/stdc++.h>
#define Debug 0
#define MAXN 200056
#define MAXM 2600
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;
using namespace std;
int arr[MAXN];
vector<int> inc, des;
int ans[MAXN] = {0};
int main ()
{
#ifdef FILE_IN
freopen(FILE_IN, "r", stdin);
#endif
// SYNC
int n;
cin >> n;
bool tag = 1;
for (int i = 0; i < n; i++)
cin >> arr[i];
for (int i = 0; i < n; ++i)
{
if ((inc.empty() && des.empty()) ||
(inc.empty() && arr[i] < des.back()) ||
(des.empty() && arr[i] > inc.back()) ||
(arr[i] > inc.back() && arr[i] < des.back()))
{
if (i < n - 1)
{
if (arr[i + 1] > arr[i])
{
inc.pb(arr[i]);
} else if (des.empty() || arr[i + 1] < des.back())
{
des.pb(arr[i]);
ans[i] = 1;
} else
{
tag = 0;
break;
}
}
} else if (inc.empty() || arr[i] > inc.back())
{
inc.pb(arr[i]);
} else if (des.empty() || arr[i] < des.back())
{
des.pb(arr[i]);
ans[i] = 1;
} else
{
tag = 0;
break;
}
}
if (tag)
{
cout << "YES" << endl;
for (int i = 0; i < n; ++i)
{
cout << ans[i] << (i == n - 1 ? '\n' : ' ');
}
} else
{
cout << "NO" << endl;
}
#ifdef FILE_IN
fclose(stdin);
#endif
return 0;
}