Title

Atcoder Beginner Contest 372(A-D)

A. delete

思路

模拟
直接输出即可

代码

void solve()
{
    std::string s;
    std::cin >> s;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] != '.')
        {
            std::cout << s[i];
        }
    }
}

B. 3^A

思路

二分
由于 \(0 \le A_i \le 10\) \((1 \le i \le N)\),可以不断二分

代码

int nums[11] = {1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049};
int ans[30];
int find(int x)
{
    int l = -1, r = 11;
    while(l + 1 < r)
    {
        int mid = (l + r) >> 1;
        //std::cout << mid << endl;
        if (nums[mid] <= x)
        {
            l = mid;
        }
        else
        {
            r = mid;
        }
    }
    return l;
}

void solve()
{
    int m = 0;
    std::cin >> m;
    //find(m);
    int cnt = 0;
    while(m)
    {
        int pos = find(m);
        //std::cout << pos << endl;
        m -= nums[pos];
        ans[++cnt] = pos;
    }
    std::cout << cnt << endl;
    for (int i = 1; i <= cnt; i++)
    {
        std::cout << ans[i] << ' ';
    }
}

C. Count ABC Again

思路

模拟
先统计出\(ABC\)字符串的个数,然后计算每一次操作产生的影响

代码

void solve()
{
    int n = 0, q = 0;
    std::string s;
    std::cin >> n >> q >> s;
    int cnt = 0;
    for (int i = 0; i < n - 2; i++)
    {
        if (s[i] == 'A' && s[i + 1] == 'B' && s[i + 2] == 'C')
        {
            cnt++;
            i += 2;
        }
    }
    //std::cout << cnt << endl;
    int x = 0;
    char ch = 0;
    for (int i = 1; i <= q; i++)
    {
        std::cin >> x >> ch;
        x--;
        if (s[x] == 'A')
        {
            if (x < n - 2 && s[x + 1] == 'B' && s[x + 2] == 'C')
            {
                cnt--;
            }
        }
        else if (s[x] == 'B')
        {
            if (x < n - 1 && x >= 1 && s[x - 1] == 'A' && s[x + 1] == 'C')
            {
                cnt--;
            }
        }
        else if (s[x] == 'C')
        {
            if (x >= 2 && s[x - 1] == 'B' && s[x - 2] == 'A')
            {
                cnt--;
            }
        }
        if (ch == 'A')
        {
            if (x < n - 2 && s[x + 1] == 'B' && s[x + 2] == 'C')
            {
                cnt++;
            }
        }
        else if (ch == 'B')
        {
            if (x < n - 1 && x >= 1 && s[x - 1] == 'A' && s[x + 1] == 'C')
            {
                cnt++;
            }
        }
        else if (ch == 'C')
        {
            if (x >= 2 && s[x - 1] == 'B' && s[x - 2] == 'A')
            {
                cnt++;
            }
        }
        s[x] = ch;
        std::cout << cnt << endl;
    }
}

D. Buildings

题意概述

  1. 给定一个长度为\(n\)的排列,第\(i\)个数为\(a_i\)

  2. 对于\(a_i\), 如果数\(j\)满足

    • \(i < j \leq N\)
    • \(a_i\)\(a_j\)之间没有大于\(a_j\)
      那么\(j\)就是合格的
  3. 对每个\(a_i\)求合格的\(j\)的个数

思路

  1. 对于一个合格的\(j\)\(a_j\)\((a_i, a_j]\)中的最大值

  2. 对于\(a_i\),就是求它后面的最长上升子序列的长度

  3. 对于最前面的数还需要考虑后面的数,求起来很困难,我们可以从后面往前看

  4. 从后往前看,对于此时的数\(a_m\), 如果它前面的数比它大,那么\(a_m\)及其后面的数无法为它前面的数做贡献,扔掉就行,如果比它小的话,子序列长度就加1了

  5. 这不就是维护一个单调递减栈就好了吗?

  6. 答案就是此时栈的大小

代码

int nums[200010];
int ans[200010];
std::stack<int> stk;
void solve()
{
    int n = 0;
	std::cin >> n;
	for (int i = 1; i <= n; i++)
	{
		std::cin >> nums[i];
	}
	stk.push(nums[n]);
	for (int i = n - 1; i >= 1; i--)
	{
		ans[i] = stk.size();
		while(!stk.empty() && stk.top() < nums[i])
		{
			stk.pop();
		}
		stk.push(nums[i]);
	}
	for (int i = 1; i <= n; i++)
	{
		std::cout << ans[i] << ' ';
	}
}
posted @ 2024-09-22 21:58  栗悟饭与龟功気波  阅读(23)  评论(0)    收藏  举报