AtCoder Beginner Contest 380 - AtCoder
A - 123233
题目及数据范围:
思路:字符串读入,用三个变量统计123的出现次数然后判断合不合法。
#include <bits/stdc++.h>
typedef long long ll;
const ll N=1000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll n , m;
void solve(){
std::string s;
std::cin >> s;
ll a = 0, b = 0, c = 0;
for (ll i = 0; i < s.length(); i++){
if(s[i] == '1') a++;
if(s[i] == '2') b++;
if(s[i] == '3') c++;
}
if(a == 1 && b == 2 && c == 3) {
std::cout << "Yes" << '\n';
} else std::cout << "No" << '\n';
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ll t = 1; //std::cin >> t;
while (t--) solve();
return 0;
}
B - Hurdle Parsing
题目及数据范围:
思路:
给你一个字符串,输出每个‘|’之间‘-’的数量。比较简单,直接找到一个|后就接着找有几个连续的-就可以,方法有很多种。
#include <bits/stdc++.h>
typedef long long ll;
const ll N=1000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
std::string s;
ll cnt = 0;
ll ans[N];
void solve(){
std::cin >> s;
for (ll i = 0; i < s.length(); i++){
if(s[i] == '|'){
ll j = i + 1;
cnt++;
ll sum = 0;
while(j < s.length() && s[j] != '|') sum++ , j++;
ans[cnt] = sum;
i = j - 1;
}
}
for (ll i = 1; i < cnt; i++) std::cout << ans[i] << ' ';
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ll t = 1; //std::cin >> t;
while (t--) solve();
return 0;
}
C - Move Segment
思路:很多人被长题目误导了,其实题目非常简单。找第k个连续的1段,然后整体移动到k-1段后面。可以存下当前段的歧视位置和长度,和上一段的位置和长度,然后找到第k段后,就把当前段复制,删除,再从前一段末尾插入就可以了。
#include <bits/stdc++.h>
typedef long long ll;
const ll N=1000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll n , k;
std::string s;
void solve(){
std::cin >> n >> k;
std::cin >> s;
ll pos1 = 0;
ll pos2 = 0;
ll pos3 = 0;
ll pos4 = 0;
ll now = 0;
for (ll i = 0; i < s.length(); i++){
if(s[i] == '1'){
if(now >= k) break;
ll j = i;
now++;
while(j < s.length() && s[j] == '1') j++;
pos3 = pos1;
pos4 = pos2;
pos1 = i;
pos2 = j - 1;
i = j;
}
}
//std::cout << pos1 << '\n';
//std::cout << pos3 << '\n';
std::string temp = s.substr(pos1 , pos2 - pos1 + 1);
s.erase(pos1 , pos2 - pos1 + 1);
s.insert(pos4 , temp);
std::cout << s << '\n';
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ll t = 1; //std::cin >> t;
while (t--) solve();
return 0;
}
D - Strange Mirroring
思路:长度特别长,不可能直接模拟。考虑到长度是倍增的。我们可以每次从当前串的前半部分找生成要查询位置的原串,递归查找。每次找这个串的中间位置,根据他们的距离,找到前半部分的原位置。直到找到小于等于原串长度的位置,就是生成要找的位置的那个字符。然后我们dfs的时候记录当前第几次,根据层数的奇偶判断要不要大小写转换。
不用int128.但是当时没想那么多
(使用快读务必把流同步打开)
每个查询是在减半,所以总复杂度nlogn
#include <bits/stdc++.h>
typedef long long ll;
const ll N=1000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
std::string s;
ll q;
__int128 k[N];
__int128 mi[70];
ll maxx = 0;
inline void read(__int128 &n){
__int128 x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
n=x*f;
}
inline void print(__int128 n){
if(n<0){
putchar('-');
n*=-1;
}
if(n>9) print(n/10);
putchar(n % 10 + '0');
}
char dfs(ll cnt , ll now){
if(now <= s.length()){
if(cnt % 2 == 0)return s[now - 1];
else {
if(s[now - 1] >= 'a' && s[now - 1] <='z') return (char)(s[now - 1] - 32);
else return (char)(s[now - 1] + 32);
}
}
ll pos = std::lower_bound(mi + 1 , mi + 1 + maxx , now) - mi;
pos--;
ll neww = now - mi[pos];
return dfs(cnt + 1 , neww);
}
void solve(){
std::cin >> s;
std::cin >> q;
mi[1] = s.length();
for (ll i = 2; i <= 64; i++){
if(mi[i - 1] * 2 > 1e18){
maxx = i - 1;
break;
}
mi[i] = 2 * mi[i - 1];
}
for (ll i = 1; i <= q; i++) read(k[i]);
for (ll i = 1; i <= q; i++){
std::cout << dfs(0 , k[i]) << ' ';
}
}
signed main(){
//std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ll t = 1; //std::cin >> t;
while (t--) solve();
return 0;
}
E - 1D Bucket Tool
题目:
思路:
看着很像数据结构题。考虑到每次要把同颜色的看成一个整体,联想到并查集。我们给整个区间分成n个段。每次合并我们把每个段合并在一起。每个大段找一个点当父亲,这样子修改操作时就可以找到大段。每次修改记得看一下前后相邻的段颜色是否一样,一样就可以合并。然后每次统计下修改后,原来颜色少了多少,新颜色多了多少,再O1输出。
复杂度大概是Oq。
#include <bits/stdc++.h>
typedef long long ll;
const ll N=1000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll n , q;
ll fa[500005];
ll shu[500005];
ll find(ll x){
if (fa[x] == x) return fa[x];
else return fa[x] = find(fa[x]);
}
struct Qujian{
ll l , r , se;
}qujian[500005];
void solve(){
std::cin >> n >> q;
for (ll i = 1; i <= n; i++) shu[i] = 1;
for (ll i = 1; i <= n; i++) {
fa[i] = i;
qujian[i].l = i;
qujian[i].r = i;
qujian[i].se = i;
}
while (q--){
ll opt;
std::cin >> opt;
if (opt == 1){
ll x , c;
std::cin >> x >> c;
ll a = find(x);
shu[qujian[a].se] -= qujian[a].r - qujian[a].l + 1;
qujian[a].se = c;
shu[qujian[a].se] += qujian[a].r - qujian[a].l + 1;
ll zuo = find(qujian[a].l - 1);
ll you = find(qujian[a].r + 1);
if(qujian[a].l - 1 >= 1 && qujian[a].se == qujian[zuo].se){
fa[zuo] = a;
qujian[a].l = qujian[zuo].l;
}
if(qujian[a].r + 1 <= n && qujian[a].se == qujian[you].se){
fa[you] = a;
qujian[a].r = qujian[you].r;
}
//std::cout << qujian[a].l << ' ' << qujian[a].r << '\n';
} else {
ll c;
std::cin >> c;
std::cout << shu[c] << '\n';
}
}
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ll t = 1; //std::cin >> t;
while (t--) solve();
return 0;
}