基本情况
前四题秒了,但是都有不够优雅的地方
F知道是线段树,但是写不出来,极其绝望
C - 343
更简洁的回文判断
MyCode
bool check_p(i64 x) {
std::string s(std::to_string(x));
int n = sz(s);
for (int i = 0; i < n / 2; i++) {
if (s[i] != s[n - i - 1]) return false;
}
return true;
}
signed main(){
constexpr int N(1E6 + 10);
std::cin >> n;
i64 ans(1);
for (i64 i = 0; i < N; i++) {
i64 num = i * i * i;
if (num > n) {std::cout << ans << '\n'; return 0;}
if (check_p(num)) ans = num;
}
std::cout << ans << '\n';
return 0;
}
STD
int main() {
i64 N;
std::cin >> N;
i64 ans = 0;
for (i64 a = 1; a * a * a <= N; a++) {
std::string s = std::to_string(a * a * a);
if (s == std::string(s.rbegin(), s.rend())) {//更简洁的回文判断
ans = a * a * a;
}
}
std::cout << ans << "\n";
return 0;
}
D - Diversity of Scores
D - Diversity of Scores (atcoder.jp)
不知道map可以erase导致的
MyCode
signed main(){
int N, T;
std::cin >> N >> T;
std::vector<i64> a(N);
std::set<i64> S(all(a));
std::map<i64, int> cnt;
cnt[0] = N;
for (int _ = 1; _ <= T; _++) {
int idx; i64 add;
std::cin >> idx >> add;
idx--;
if (cnt.count(a[idx])) {
cnt[a[idx]]--;
if (cnt[a[idx]] == 0) {
S.erase(a[idx]);
}
}
a[idx] += add;
cnt[a[idx]]++;
S.insert(a[idx]);
std::cout << sz(S) << '\n';
}
return 0;
}
STD
signed main(){
int N, T;
std::cin >> N >> T;
std::vector<i64> a(N);
std::map<i64, int> cnt;
cnt[0] = N;
for (int _ = 1; _ <= T; _++) {
int idx; i64 add;
std::cin >> idx >> add;
idx--;
if (--cnt[a[idx]] == 0) cnt.erase(a[idx]);//直接用map执行删除操作就行
a[idx] += add;
cnt[a[idx]]++;
std::cout << sz(cnt) << '\n';
}
return 0;
}
F - Second Largest Query
F - Second Largest Query (atcoder.jp)
线段树掌握不到位
这里只需要维护次大值,并不需要主席树
而且也不需要通过map等暴力统计次大值数量,可以优雅地直接用线段树在合并时维护
#include <bits/stdc++.h>
using i64 = long long;
template<class Info>
struct SegmentTree {
int n;
std::vector<Info> info;
SegmentTree() : n(0) {}
SegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
SegmentTree(std::vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(std::vector(n_, v_));
}
template<class T>
void init(std::vector<T> init_) {
n = init_.size();
info.assign(4 << std::__lg(n), Info());
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
info[p] = init_[l];
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
pull(p);
};
build(1, 0, n);
}
void pull(int p) {
info[p] = info[2 * p] + info[2 * p + 1];
}
void modify(int p, int l, int r, int x, const Info &v) {
if (r - l == 1) {
info[p] = v;
return;
}
int m = (l + r) / 2;
if (x < m) {
modify(2 * p, l, m, x, v);
} else {
modify(2 * p + 1, m, r, x, v);
}
pull(p);
}
void modify(int p, const Info &v) {
modify(1, 0, n, p, v);
}
Info rangeQuery(int p, int l, int r, int x, int y) {
if (l >= y || r <= x) {
return Info();
}
if (l >= x && r <= y) {
return info[p];
}
int m = (l + r) / 2;
return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
Info rangeQuery(int l, int r) {
return rangeQuery(1, 0, n, l, r);
}
template<class F>
int findFirst(int p, int l, int r, int x, int y, F pred) {
if (l >= y || r <= x || !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
int res = findFirst(2 * p, l, m, x, y, pred);
if (res == -1) {
res = findFirst(2 * p + 1, m, r, x, y, pred);
}
return res;
}
template<class F>
int findFirst(int l, int r, F pred) {
return findFirst(1, 0, n, l, r, pred);
}
template<class F>
int findLast(int p, int l, int r, int x, int y, F pred) {
if (l >= y || r <= x || !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
int res = findLast(2 * p + 1, m, r, x, y, pred);
if (res == -1) {
res = findLast(2 * p, l, m, x, y, pred);
}
return res;
}
template<class F>
int findLast(int l, int r, F pred) {
return findLast(1, 0, n, l, r, pred);
}
};
struct Info {
//最大值,最大值个数,次大值,次大值个数
int mx1 = -1;
int cnt1 = 0;
int mx2 = -2;
int cnt2 = 0;
};
Info operator+(Info a, Info b) {
//区间合并维护次大值和次大值个数
if (a.mx1 == b.mx1) {//如果两个区间最大值相等
if (a.mx2 < b.mx2) {//维护次大值
std::swap(a, b);
}
a.cnt1 += b.cnt1;//维护最大值个数
if (a.mx2 == b.mx2) {//如果两者次大值相等
a.cnt2 += b.cnt2;//相加次大值
}
return a;
}
//如果两个区间最大值不等
if (a.mx1 < b.mx1) {//先把情况变成a最大值最大
std::swap(a, b);
}
if (b.mx1 > a.mx2) {//如果b的最大值比a的次大值大(此时a的最大值肯定是最大的,所以b的最大值就是次大值)
a.mx2 = b.mx1;//维护次大值
a.cnt2 = b.cnt1;//显然次大值改变了,所以个数改成b的最大值的个数
} else if (b.mx1 == a.mx2) {//两个一样,就相加
a.cnt2 += b.cnt1;
}
return a;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int N, Q;
std::cin >> N >> Q;
std::vector<int> A(N);
for (int i = 0; i < N; i++) {
std::cin >> A[i];
}
SegmentTree<Info> seg(N);
for (int i = 0; i < N; i++) {
seg.modify(i, Info{A[i], 1, -1, 0});
//单点修改,最大值等于自己,个数为1.没有次大值,所以设成{0, 1}
}
while (Q--) {
int o;
std::cin >> o;
if (o == 1) {
int p, x;
std::cin >> p >> x;
p--;
seg.modify(p, {x, 1, -1, 0});
} else {
int l, r;
std::cin >> l >> r;
l--;
std::cout << seg.rangeQuery(l, r).cnt2 << "\n";
}
}
return 0;
}
标签:std,AtCoder,cnt,Beginner,idx,int,Info,次大值,343
From: https://www.cnblogs.com/kdlyh/p/18049472