2023-01-16 00:50阅读: 559评论: 2推荐: 1

AtCoder Beginner Contest 285

A - Edge Checker 2 (abc285 a)

题目大意

给定如下一棵树。

一棵树

给定 a,b(a<b),问两者是否有连边。

解题思路

观察数可发现其为二叉树,两者有连边当且仅当b=2ab=2a+1

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int a, b;
cin >> a >> b;
if (a * 2 != b && a * 2 + 1 != b)
cout << "No" << '\n';
else
cout << "Yes" << '\n';
return 0;
}


B - Longest Uncommon Prefix (abc285 b)

题目大意

给定一个长度为n字符串s,对于每个i[1,n1] ,找到最大的l使得

  • i+lN
  • k[1,l],sksk+i

解题思路

数据范围不大,暴力即可。

即对于每个i, 枚举 l1到第一个 slsk+l为止。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n;
string s;
cin >> n >> s;
auto solve = [&](int x){
int ans = 0;
while(ans < n - x){
if (s[ans] == s[ans + x])
break;
++ ans;
}
return ans;
};
for(int i = 1; i < n; ++ i){
cout << solve(i) << '\n';
}
return 0;
}


C - abc285_brutmhyhiizp (abc285 c)

题目大意

有一堆字符串,其字典序顺序为:

  • 'a', 'b', ..., 'z', 'aa', 'ab', ..., 'az', 'ba', 'bb', ..., 'bz', ..., 'za', 'zb', ..., 'zz', 'aaa', 'aab', ..., 'aaz', 'aba', 'abb', ..., 'abz', ..., 'zzz', 'aaaa', ...

现给定其中一个字符串,问其字典序大小。

解题思路

这题是abc171 c的反过来形式。

每个位置,以a-z的26为一循环,但第一次循环时还有一个0a可以看成是0a)。所以 a应当看成数字1

因此高位转低位时,进位时26,但末尾数字减去'A'后还要加一。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
string s;
cin >> s;
LL ans = 0;
for(auto &i : s){
ans = ans * 26 + (i - 'A' + 1);
}
cout << ans << '\n';
return 0;
}


D - Change Usernames (abc285 d)

题目大意

给定n对字符串 si,ti。表示有 n个人,原本叫 si,现在需要改名为 ti

你现在要处理该请求,每次只能改一个人的名,问改名过程中会不会出现重名,即一个人改成ti了,但还有另一个还没改名sj=ti

解题思路

字符串si改成 ti,则从 si连一条有向边到 ti

如果存在一个环,则改名过程必定重名。

有向边判环的方法即拓扑排序。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n;
cin >> n;
vector<string> s(n), t(n);
set<string> qwq;
map<string, int> tr;
for(int i = 0; i < n; ++ i){
cin >> s[i] >> t[i];
qwq.insert(s[i]);
qwq.insert(t[i]);
}
int cnt = 0;
for(auto &i : qwq){
tr[i] = cnt;
++ cnt;
}
vector<int> du(cnt);
vector<vector<int>> edge(cnt);
for(int i = 0; i < n; ++ i){
int u = tr[s[i]];
int v = tr[t[i]];
edge[u].push_back(v);
du[v] ++;
}
queue<int> team;
for(int i = 0; i < cnt; ++ i){
if (du[i] == 0)
team.push(i);
}
while(!team.empty()){
auto u = team.front();
-- cnt;
team.pop();
for(auto &v : edge[u]){
du[v] --;
if (du[v] == 0)
team.push(v);
}
}
if (cnt)
cout << "No" << '\n';
else
cout << "Yes" << '\n';
return 0;
}


E - Work or Rest (abc285 e)

题目大意

一周有n天。 给定一个长度为n的数组 a

你需要指定 至少一天为休息日,其余为工作日。要求最大化工作日的产能。

一个工作日的产能定义为amin(x,y),其中 x是该日距离过去最近的休息日的天数, y是该日距离未来最近的休息日天数。注意周与周之间是连贯的,第一周的第一天的过去可以是上一周。

解题思路

如果不考虑连贯的影响,即认为一周是独立的,可以设dp[i]表示第 i天为休息日的情况下最大的产生值。转移时枚举上一次休息日的天数 j

观察 j|j+1,j+2,...,i1|i,中间 j+1i1的产能值,即为 a1,a2,...,a2,a1,即下标是一个先递增后递减的规律,就是一个 a的前缀和的两倍,根据奇偶性可能多出一个ai。这样转移可以 O(1)。复杂度就是 O(n2)

但是一周并不是独立的,这样的方程具有后效性,归根结底就在于我们不知道一周第一次的休息日的日子,无法算出该日子之前和最后一个休息日之后的这几天的产能贡献。但如果设dp[i][j]表示第一次休息日在第 i天,然后在第 j天也是休息日的最大产能,其复杂度为 O(n3)

但是,注意到天与天之间没有区别的,意思就是说,如果我们确定了第一次休息日的天数a,以及最后一次休息日的天数b,那这两个休息日之间,里面休息日任意选,获得的产生最大值,其实就是 dp[ba]

因此我们预处理 dp[i],然后枚举第一次休息日a和最后一次休息日 b所在天数,那答案 dp[ba]加上前 a天和后 b天工作日的产能贡献了。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n;
cin >> n;
vector<LL> a(n);
for(auto &i : a)
cin >> i;
vector<LL> sum(n);
partial_sum(a.begin(), a.end(), sum.begin());
vector<LL> dp(n + 1, 0);
auto solve = [&](int len){
int dig = (len & 1);
int half = (len >> 1);
LL tmp = 0;
if (half)
tmp += 2ll * sum[half - 1];
if (dig)
tmp += a[half];
return tmp;
};
for(int i = 1; i <= n; ++ i){
for(int j = 0; j < i; ++ j){
dp[i] = max(dp[i], dp[j] + solve(i - j - 1));
}
}
LL ans = 0;
for(int i = 0; i < n; ++ i)
for(int j = i; j < n; ++ j){
ans = max(ans, dp[j - i] + solve(i + n - j - 1));
}
cout << ans << '\n';
return 0;
}


F - Substring of Sorted String (abc285 f)

题目大意

给定一个字符串s,定义字符串 t为串 s各字母从小到大排序的字符串。进行 q次操作,操作分两种:

  • 1 x c,令 sx=c
  • 2 x y,问s[x..y]是不是 串t的一个子串

解题思路

对于询问,其等价于:串a是串 t的子串,说明

  • 其串是递增的
  • 除首字母和末字母之外,中间的字母出现次数都是串 s中出现的次数

初步想法是预处理出l[i],r[i]数组表示第 i个字母的左边、右边第一个非该字母的位置。

对于一个询问 2s[r[x],l[y]]就是中间字母,其长度和各字母的出现次数都必须符合上述要求,也就是说这段字符串必须是确定的某一个,可以用字符串hash来判断,而由于操作一涉及到修改(该确定的字符串的hash可以在O(26)的复杂度计算出),因此需要用线段树hash的方式维护其hash值。

同时l[i],r[i]数组同样也要维护,考虑操作一的影响,这涉及到区间修改,需要用线段树维护,但逻辑稍微复杂,写起来比较麻烦。

神奇的代码


G - Tatami (abc285 g)

题目大意

给定一个h×w的网格,格子上有 1 2 ?这三个符号,要求用1×11×2(可旋转)的矩形覆盖。其中 1的格必须被 1×1的格子覆盖, 2的格必须被1×2的格子覆盖, ?的则随意。

问是否存在一种方案。

解题思路

<++>

神奇的代码


Ex - Avoid Square Number (abc285 h)

题目大意

给定n和一个长度为 k的序列 E,要求求一个长度为 n的正整数序列的数量,满足:

  • 所有元素都不是平方数
  • 所有元素的乘积为 i=1KpiEi

其中 pi是第 i小的质数。

解题思路

<++>

神奇的代码


本文作者:~Lanly~

本文链接:https://www.cnblogs.com/Lanly/p/17054546.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ~Lanly~  阅读(559)  评论(2编辑  收藏  举报
历史上的今天:
2017-01-16 二分图匹配之最佳匹配——KM算法
2017-01-16 二分图匹配之最大匹配——匈牙利算法
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.