The 3rd Universal Cup. Stage 15: Chengdu

PHarr發表於2024-11-03

A. Arrow a Row

一個簡單的構造題,構造的思路是先把又側的連續>放滿,再從左側逐個開始放,如果是>就放一個長度為 5 的,如果是-,可以一次性直接把連續的都放了。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

using vi = vector<int>;
using pii = pair<int,int>;


string check(int n, vector<pii> op) {
	string s(n + 1, '*');
	for(auto [x, len] : op) {
		s[x] = s[x + len - 1] = s[x + len - 2] = s[x + len - 3] = '>';
		for(int i = x + 1; i <= x + len - 4; i ++)
			s[i] = '-';
		cout << s << "\n";
	}
	return s;
}

void solve() {
	string s;
	cin >> s;

	int n = s.size() - 1;

	if(s[0] != '>' or s[n] != '>' or s[n - 1] != '>' or s[n - 2] != '>'){
		cout << "No\n";
		return;
	}
	bool ok = false;
	for(int i = 1; i <= n - 3; i ++) {
		if(s[i] == '-') {
			ok = true;
			break;
		}
	}

	if(ok == false){
		cout << "No\n";
		return;
	}

	vector<pii> op;
	int lst = -1;
	for(int i = n; i >= 0; i --){
		if(s[i] == '>' and s[i - 1] == '>' and s[i - 2] == '>') {
			op.emplace_back(i - 4, 5);
			i = i - 2;
		} else if(s[i] == '>' and s[i - 1] == '>') {
			op.emplace_back(i - 3, 5);
			lst = i - 2;
			break;
		} else if(s[i] == '>') {
			op.emplace_back(i - 2, 5);
			lst = i - 1;
			break;
		} else {
			lst = i;
			break;
		}
	}


	for(int i = 0; i <= lst; i ++){
		if(s[i] == '>') {
			if(s[i + 1] == '-'){
				int len = 4, j = i;
				while(s[i + 1] == '-')
					i ++, len ++;
				op.emplace_back(j, len);
			} else {
				op.emplace_back(i, 5);
			}
		} else {
			assert(false);
		}
	}

	cout << "Yes " << op.size() << "\n";
	for(auto [x, y]: op) cout << x + 1 << " " << y << "\n"; 
	// check(n, op);
	return;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int T;
	cin >> T;
	while(T --)
		solve();
	return 0;
}

G. Expanding Array

這個題,我的做法就是直接暴搜,然後猛猛加最佳化就過了。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = uint64_t;

using vi = vector<int>;
using pii = pair<int,int>;

const i64 P = 1e10;
unordered_set<i64> vis;
unordered_set<int> cnt;


void dfs(int l, int r) {
	if(l > r) swap(l, r);
	if(vis.insert((i64)l * P + r).second == false) return;
	
	int mid = (l & r);
	cnt.insert(mid);

	if(l != mid and mid != r and mid != 0) dfs(l, mid), dfs(mid, r);

	mid = (l | r);
	cnt.insert(mid);
	if(l != mid and mid != r and mid != 0) dfs(l, mid), dfs(mid, r);

	mid = (l ^ r);
	cnt.insert(mid);

	if(l != mid and mid != r and mid != 0) dfs(l, mid), dfs(mid, r);

	return ;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n;
	cin >> n;
	vi a(n);
	for(int i = 0; i < n; i ++) 
		cin >> a[i], cnt.insert(a[i]);

	cnt.insert(0);

	for(int i = 1; i < n; i ++)
		if(a[i - 1] != a[i]) dfs(a[i - 1], a[i]);
	cout << cnt.size();
	return 0;
}

I. Good Partitions

首先我們求出序列中每一段連續不下降子串的長度,長度的 gcd 一定是可以的,並且 gcd 的因數也是可以的。除此之外,還有一種情況是捨去最後一段的 gcd 及其長度也是可行。

如果說我們可以求出 gcd,我們就可以\(O(\sqrt N\))的求出所有的因子。

現在我們考慮如何快速的實現修改和查詢 gcd,如果\(a[i] > a[i+1]\),則說明\(i\) 是一個不下降子串的結尾。我們可以新開一個陣列\(b[i]\),如果$a[i] > a[i + 1] $ 則\(b[i] = i\),否則\(b[i] = -1\)。此時我們找到每一個不是\(-1\)的數字,以及他前面第一個不是\(-1\) 的數字,我們就可以快速的求出不下降子串的長度。

這樣的話,我們需要就是單點修改和區間查詢,我們可以用線段實現這個操作。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = std::vector<int>;


struct Info {
    int d, li, ri;

    Info() {
        d = 0;
        li = ri = -1;
    }

    Info(int d, int li, int ri) : d(d), li(li), ri(ri) {}

    Info operator+(const Info &b) {
        Info res = *this;

        if (res.li == -1) res.li = b.li;
        if (b.ri != -1) res.ri = b.ri;
        res.d = gcd(res.d, b.d);

        if (ri != -1 and b.li != -1)
            res.d = gcd(res.d, b.li - ri);
        return res;
    }
};

struct Node {
    i32 l, r;
    Info info;

    Node *left, *right;

    Node() {};

    Node(int p, int x) {
        l = p, r = p;
        info = Info(0, x, x);
        left = right = nullptr;
    }

    Node(int l, int r, Node *left, Node *right) : l(l), r(r), left(left), right(right) {
        info = left->info + right->info;
    }
};


Node *build(int l, int r, const vi &b) {
    if (l == r) return new Node(l, b[l]);

    i32 mid = (l + r) / 2;
    auto left = build(l, mid, b);
    auto right = build(mid + 1, r, b);

    return new Node(l, r, left, right);
}

void modify(int p, int x, Node *cur) {
    if (cur->l == p and p == cur->r) {
        cur->info.li = cur->info.ri = x;
        return;
    }
    int mid = (cur->l + cur->r) / 2;
    if (p <= mid) modify(p, x, cur->left);
    else modify(p, x, cur->right);
    cur->info = cur->left->info + cur->right->info;
}

Info query(int n, Node *cur) {
    if (cur->info.ri != n) return cur->info;
    if (cur->l == cur->r) return Info();

    Info res;
    if (cur->left->info.ri != n)
        res = res + cur->left->info;
    else
        res = res + query(n, cur->left);

    if (cur->right->info.ri != n)
        res = res + cur->right->info;
    else
        res = res + query(n, cur->right);

    return res;
}

void solve() {
    int n, q;
    cin >> n >> q;

    vi a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];

    vi b(n + 1, -1);
    for (int i = 1; i < n; i++) {
        if (a[i] > a[i + 1]) {
            b[i] = i;
        }
    }
    b[0] = 0, b[n] = n;


    auto root = build(0, n, b);
    int d1 = root->info.d;
    int d2 = query(n, root).d;
    unordered_set<int> cnt;

    if (d2 == 0) {
        cout << n << "\n";
    } else {
        for (int i = 1; i * i <= d1; i++) {
            if (d1 % i != 0) continue;
            cnt.insert(i);
            if (d1 / i != i) cnt.insert(d1 / i);
        }
        for (int i = 1; i * i <= d2 and d1 != d2; i++) {
            if (d2 % i != 0) continue;
            cnt.insert(i);
            if (d2 / i != i) cnt.insert(d2 / i);
        }
        cout << cnt.size() << "\n";
    }

    for (int idx, val, ok; q; q--) {
        cin >> idx >> val;

        a[idx] = val, ok = 1;
        if (idx - 1 >= 1 and a[idx - 1] > a[idx]) {
            if (b[idx - 1] != idx - 1) {
                b[idx - 1] = idx - 1;
                modify(idx - 1, idx - 1, root);
                ok = 0;
            }
        } else if (idx - 1 >= 1) {
            if (b[idx - 1] != -1) {
                b[idx - 1] = -1;
                modify(idx - 1, -1, root);
                ok = 0;
            }
        }

        if (idx + 1 <= n and a[idx] > a[idx + 1]) {
            if (b[idx] != idx) {
                b[idx] = idx;
                modify(idx, idx, root);
                ok = 0;
            }
        } else if (idx + 1 <= n) {
            if (b[idx] != -1) {
                b[idx] = -1;
                modify(idx, -1, root);
                ok = 0;
            }
        }

        if (ok) {
            if (d2 == 0) cout << n << "\n";
            else cout << cnt.size() << "\n";
            continue;
        }

        d1 = root->info.d;
        d2 = query(n, root).d;
        cnt.clear();

        if (d2 == 0) {
            cout << n << "\n";
        } else {
            for (int i = 1; i * i <= d1; i++) {
                if (d1 % i != 0) continue;
                cnt.insert(i);
                if (d1 / i != i) cnt.insert(d1 / i);
            }
            for (int i = 1; i * i <= d2 and d1 != d2; i++) {
                if (d2 % i != 0) continue;
                cnt.insert(i);
                if (d2 / i != i) cnt.insert(d2 / i);
            }
            cout << cnt.size() << "\n";
        }
    }
    return;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int T;
    cin >> T;

    while (T--)
        solve();

    return 0;
}

J. Grand Prix of Ballance

讀題加模擬就做完了

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;
using pii = pair<int,int>;


void solve() {
	int n, m, q;
	cin >> n >> m >> q;
	vector<vi> finsh(n + 1);
	vector<set<int>> vist(n + 1);

	int now_Level = -1;


	for(int op, id, x; q; q --) {
		cin >> op;
		if(op == 1) {
			cin >> x;
			now_Level = x;
		} else if(op == 2) {
			cin >> id >> x;
			if(x != now_Level) continue;
			if(vist[x].insert(id).second == false) continue;
			if(x == now_Level)
				finsh[x].push_back(id);
		} else {
			cin >> id >> x;
			if(x != now_Level) continue;
			vist[x].insert(id);
		}
	}

	vi points(m + 1);
	for(int i = 1; i <= n; i ++) {
		for(int v = m; auto j : finsh[i])
			points[j] += v, v --;
	}

	vi rank(m);

	iota(rank.begin(), rank.end(), 1);

	ranges::sort(rank, [&](int x, int y) -> bool {
		if(points[x] != points[y]) return points[x] > points[y];
		return x < y;
	});
	for(auto i : rank)
		cout << i << " " << points[i] << "\n";

}

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int T;
	cin >> T;
	while(T --)
		solve();
	return 0;
}

L. Recover Statistics

簽到題

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

using vi = std::vector<int>;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	i64 P50, P95, P99;
	cin >> P50 >> P95 >> P99;
	cout << 100 << "\n";
	for(int i = 1; i <= 50; i ++)
		cout << P50 << " ";
	for(int i = 1; i <= 45; i ++)
		cout << P95 << " ";
	for(int i = 1; i <= 4; i ++)
		cout << P99 << " ";
	cout << P99 + 1 << "\n";

	return 0;
}

相關文章