Loading

AtCoder Beginner Contest 347




B - Substring

难度: ⭐

题目大意

给你一个由小写英文字母组成的字符串S; 请问S有多少个不同的非空子串?

解题思路

数据很小, 暴力就行;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res = inf;
set<string> st;
signed main(){
    IOS;
    string s;
    cin >> s;
    for(int i = 0; i < s.size(); i++){
        for(int j = 1; i + j <= s.size(); j++){
            string str = s.substr(i, j);
            st.insert(str);
        }
    }
    cout << st.size();
	return 0;
}




C - Ideal Holidays

难度: ⭐⭐⭐

题目大意

小莫的一周有A + B天, 前A天是假期, 后B天是工作日; 小莫有n个计划, 第i个计划安排在第Di天后; 但是小莫忘了今天是这周的第几天, 请问小莫有可能完成这些计划吗;

解题思路

首先我们先把所有Di对(A + B)取余后排序; 我们画一个由A + B + A组成的坐标轴, 小莫的位置在前A + B中, 设为pos, 那么这些任务就分布在pos到(A+B+C); 然后我们可以分类讨论了;
首先我们可以用最晚的任务减去最早的任务时间, 看是否小于等于A, 这样小莫既可以在第一个A的开头, 也可以在中间B的末尾;
如果不满足上述条件, 那么小莫就只能在第一个A的时间里, 并且由于时间跨度大于A, 那么也就是这样任务一定会跨越时间B, 也就是说有两个相邻任务之间的间隔要大于等于B;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res;
int A, B;
int p[N];
bool check(){
    sort(p + 1, p + 1 + n);
    int len = p[n] - p[1] + 1;
    if(len <= A) return true;
    for(int i = 2; i <= n; i++){
        if(p[i] - p[i - 1] - 1 >= B) return true;
    }
    return false;
}
signed main(){
    IOS;
    cin >> n >> A >> B;
    bool f = false;
    for(int i = 1; i <= n; i++){
        cin >> p[i];
        p[i] %= (A + B);
    }
    if(check()) cout << "Yes";
    else cout << "No";
	return 0;
}




D - Popcount and XOR

难度: ⭐⭐⭐

题目大意

给定数字a, b, C; 要求找出数字x, y; 要求x二进制中1的个数为a, y二进制中1的个数为b, x异或y的结果是C;

解题思路

因为a, b的范围都小于等于60, C也小于等于2的60次方; 所以我们按位遍历C, 如果某一位上为1, 那么我们就贪心地看a和b谁多就把谁的这一位赋为1; 这样结束后剩下的a和b一定是相等的, C此时所有位上的1都被处理的, 剩下的都是0, 自然要求剩下x和y在这些位上的数字相同; 如果此时a和b不为0, 那么我们遍历位数, 如果x和y的这一位都是0, 那么我们就把这些都改为1即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, k;
int p[N];
signed main(){
    IOS;
    cin >> n >> m >> k;
    int a = 0, b = 0;
    int cnt = 1;
    bool f = true;
    while(k){
        if(k & 1){
            if(n > m){
                a += cnt;
                n--; 
            }
            else {
                b += cnt;
                m--;
            }
            if(n < 0 || m < 0){
                f = false;
                break;
            }
        }
        cnt *= 2;
        k >>= 1;
    }
    if(n != m) f = false;
    for(int i = 0; i < 62 && n; i++){
        if(!(a >> i & 1) && !(b >> i & 1)){
            a |= 1ll << i;
            b |= 1ll << i;
            n--, m--;
        }
    }
    if(n || m) f = false;
    if(f) cout << a << ' ' << b;
    else cout << -1;
	return 0;
}




E - Set Add Query

难度: ⭐⭐⭐(⭐)

题目大意

现有一个集合S和一个长度为n的空数组A, |S|表示集合S中元素的个数; 现在进行Q次操作, 每次给出一个整数x, 如果S中有x, 那么就删除x, 否则就添加x; 然后对于S中的每个数t, 让At加上|S|;

解题思路

因为数据范围较大, 所以要考虑用O(n)的方式解决; 首先我们记录每次操作后的|S|, 然后记录其前缀和; 而对于每次操作给出的x, 我们要记录其在集合S中存在了多久, 然后用前缀和一次性地添加; 当添加x时, 我们记录x的st, 然后删除时间就是x的ed, 并且在删除时就可以结算了;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, k;
set<int> s;
int p[N], sum[N];
struct node{
    int st, ed;
}f[N];
signed main(){
    IOS;
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int a;
        cin >> a;
        if(s.count(a)){
            s.erase(a);
            p[a] += sum[i - 1] - sum[f[a].st - 1];
            f[a].st = 0;
        }
        else {
            s.insert(a);
            f[a].st = i;
        }
        sum[i] = sum[i - 1] + s.size();
    }
    for(int i = 1; i <= n; i++){
        if(f[i].st){
            p[i] += sum[m] - sum[f[i].st - 1];
        }
        cout << p[i] << ' ';
    }
	return 0;
}




F - Non-overlapping Squares

难度: ⭐⭐⭐⭐

posted @ 2024-04-14 20:07  mostimali  阅读(18)  评论(0编辑  收藏  举报