AtCoder Beginner Contest 393


A - Poisonous Oyster

题意:有四个食物,有一个有毒,第一个人吃了第1、2个,第二个吃了第1、3个,给出两个人是否中毒,求有毒的食物。

都中毒那么就是第一个,第一个人中毒就是第二个,第二个人中毒是第三个,否则是第四个。

点击查看代码
void solve() {
	std::string s, t;
	std::cin >> s >> t;
	if (s == "sick" && t == "sick") {
		std::cout << 1 << "\n";
	} else if (s == "sick") {
		std::cout << 2 << "\n";
	} else if (t == "sick") {
		std::cout << 3 << "\n";
	} else {
		std::cout << 4 << "\n";
	}
}

B - A..B..C

题意:给你一个只包含ABC的字符串,求有多少等于ABC的子序列使得三个字符出现的位置是等差序列。

枚举B的位置往两边扩展即可。

点击查看代码
void solve() {
	std::string s;
	std::cin >> s;
	int n = s.size();
	int ans = 0;
	for (int i = 0; i < n; ++ i) {
		if (s[i] == 'B') {
			int l = i - 1, r = i + 1;
			while (l >= 0 && r < n) {
				if (s[l] == 'A' && s[r] == 'C') {
					++ ans;
				}

				-- l, ++ r;
			}
		}
	}

	std::cout << ans << "\n";
}

C - Make it Simple

题意:求一个图里有多少自环边和重边。

set记录出现过的边,然后统计答案。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::set<std::pair<int, int>> s;
    int ans = 0;
    for (int i = 0; i < m; ++ i) {
    	int u, v;
    	std::cin >> u >> v;
    	if (u > v) {
    		std::swap(u, v);
    	}

    	if (u == v || s.count({u, v})) {
    		++ ans;
    	}

    	s.insert({u, v});
    }

    std::cout << ans << "\n";
}

D - Swap to Gather

题意:给你一个01串,你每次可以交换两个相邻的位置上的数,求让所有1连在一起的最小操作数。

预处理一个后缀的1都挨着i的最小操作数sufi,然后从前往后枚举i,则前面和后面都往i移过来的操作数就是prei+sufi+1

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    std::vector<i64> suf(n + 2);
    int cnt = 0;
    for (int i = n; i >= 1; -- i) {
    	suf[i] = suf[i + 1];
    	if (s[i - 1] == '0') {
    		suf[i] += cnt;
    	} else {
    		++ cnt;
    	}
    }

    cnt = 0;
    i64 pre = 0;
    i64 ans = 1e18;
    for (int i = 1; i <= n; ++ i) {
    	if (s[i - 1] == '0') {
    		pre += cnt;
    	} else {
    		++ cnt;
    	}

    	ans = std::min(ans, pre + suf[i + 1]);
    }

    std::cout << ans << "\n";
}

E - GCD of Subset

题意:给你一个数组,求包含aik个数的所有组合中gcd的最大值。

预处理每个数作为因子时在数组里有多少倍数,然后对于每个倍数个数大于等于k的数更新它的所有倍数的答案。

点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    const int N = 1e6 + 5;
    std::vector<std::vector<int>> factor(N);
    for (int i = 1e6; i >= 1; -- i) {
    	for (int j = i; j < N; j += i) {
    		factor[j].push_back(i);
    	}
    }

    std::vector<int> cnt(N);
    for (int i = 0; i < n; ++ i) {
    	for (auto & x : factor[a[i]]) {
    		++ cnt[x];
    	}
    }

    std::vector<int> ans(N);
    for (int i = 1; i < N; ++ i) {
    	if (cnt[i] >= k) {
    		for (int j = i; j < N; j += i) {
    			ans[j] = i;
    		}
    	}
    }

    for (int i = 0; i < n; ++ i) {
    	std::cout << ans[a[i]] << "\n";
    }
}

F - Prefix LIS Query

题意:给你一个数组,每次求一个前缀所有小于等于x的数可以组成的最长上升子序列长度是多少。

考虑离线,然后用树状数组按顺序处理最长上升子序列的dp值,那么对于第i个位置要求小于等于x的答案就是[1,x]的最大值。

点击查看代码
template <class T>
struct Fenwick {
    int n;
    std::vector<T> tr;

    Fenwick(int _n) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        tr.assign(_n + 1, T{});
    }

    void add(int x, const T &v) {
        for (int i = x; i <= n; i += i & -i) {
            tr[i] = tr[i] + v;
        }
    }

    T query(int x) {
        T res{};
        for (int i = x; i; i -= i & -i) {
            res = res + tr[i];
        }
        return res;
    }

    T sum(int l, int r) {
        return query(r) - query(l - 1);
    }
};

struct Info {
	int max;
};

Info operator + (Info a, Info b) {
	return {std::max(a.max, b.max)};
}

void solve() {
    int n, q;
    std::cin >> n >> q;
    std::vector<int> a(n + 1);
    std::vector<int> b;
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    	b.push_back(a[i]);
    }

    std::vector<std::vector<std::pair<int, int>>> Q(n + 1);
    for (int i = 0; i < q; ++ i) {
    	int r, x;
    	std::cin >> r >> x;
    	b.push_back(x);
    	Q[r].push_back({x, i});
    }

    std::sort(b.begin(), b.end());
    b.erase(std::unique(b.begin(), b.end()), b.end());

    auto get = [&](int x) -> int {
    	return std::lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
    };

    int m = b.size();

    Fenwick<Info> tr(m + 1);
    std::vector<int> ans(q);
    for (int i = 1; i <= n; ++ i) {
    	a[i] = get(a[i]);
    	int v = tr.query(a[i] - 1).max + 1;
    	tr.add(a[i], Info{v});
    	for (auto & [x, id] : Q[i]) {
    		x = get(x);
    		ans[id] = tr.query(x).max;
    	}
    }

    for (int i = 0; i < q; ++ i) {
    	std::cout << ans[i] << "\n";
    }
}
posted @   maburb  阅读(127)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示