天梯赛训练

天梯赛训练

A - A 洛谷 - P2669

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	i64 n = 0, ans = 0;
	cin >> n;
	i64 i = 1, t = 0;
	while (t < n) {
		ans += i * min(i, n - t);
		t += i;
		i ++;
	}
	cout << ans << '\n';

	return 0;
}

B - B 洛谷 - P5660

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int num = 0;
	string s;
	cin >> s;
	for(auto  i : s)
		num += (i == '1');
	cout << num << '\n';
	
	return 0;
}

C - C 洛谷 - P5015

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	string s;
	getline(cin, s);
	int num = s.size();
	for (auto i : s)
		num -= (i == ' ');
	cout << num << '\n';

	return 0;
}

D - D 洛谷 - P5681

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	i64 a,b,c;
	cin >> a >> b >> c;
	if(a * a > b * c) cout << "Alice\n";
	else cout << "Bob\n";

	return 0;
}

E - E 洛谷 - P1190

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, m;
	cin >> n >> m;
	vector<int> w(n);
	int mx = 0, sum = 0;
	for (auto &i : w) {
		cin >> i;
		mx = max(mx, i);
		sum += i;
	}


	if (n <= m) {
		cout << mx << '\n';
	} else {
		vector<int> d(m);
		for (int i = 0; i < n; i ++) {
			int now = INT_MAX, loc = -1;
			for (int j = 0; j < m; j ++) {
				if (d[j] < now) {
					now = d[j], loc = j;
				}
			}
			d[loc] += w[i];
		}
		int ans = 0;
		for (int i = 0; i < m; i ++)
			ans = max(ans, d[i]);
		cout << ans << '\n';
	}

	return 0;
}

F - F 洛谷 - P7071

按照其二进制对应输出\(2^k\)即可

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n;
	cin >> n;

	if (n & 1) {
		cout << "-1\n";
	} else {
		for (int i = 30; i >= 0; i --) {
			if (n >= (1 << i)) {
				cout << (1 << i) << ' ';
				n -= (1 << i);
			}
		}
	}

	return 0;
}

G - G 洛谷 - P2670

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, m;
	cin >> n >> m;
	vector<string> s(n);
	for (auto &i : s) cin >> i;

	int u[] = {1,1,1,-1,-1,-1,0,0},v[] = {1,0,-1,1,0,-1,1,-1};
	vector ans(n, vector<int>(m));
	for (int i = 0; i < n; i ++) {
		for (int j = 0; j < m; j ++) {
			if (s[i][j] == '*') {
				for (int k = 0; k < 8; k ++) {
					int x = i + u[k];
					int y = j + v[k];
					if (x >= 0 && x < n && y >= 0 && y < m)
						ans[x][y] ++;
				}
			}
		}
	}
	for (int i = 0; i < n; i ++) {
		for (int j = 0; j < m; j ++)
			if (s[i][j] == '*') cout << s[i][j];
			else cout << ans[i][j];
		cout << '\n';
	}

	return 0;
}

H - H 洛谷 - P1098

模拟;

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int p1, p2, p3;
    string s;
    cin >> p1 >> p2 >> p3 >> s;

    string ans = "";
    ans += s[0];
    for (int i = 1; i < s.size() - 1; i ++) {
        if (s[i] == '-' && s[i + 1] > s[i - 1]) {
            if (s[i - 1] + 1 == s[i + 1]) continue;

            string str = "";
            char st, ed;
            st = s[i - 1] + 1, ed = s[i + 1] - 1;

            if (s[i - 1] >= '0' && s[i + 1] <= '9') {
                for (char j = st; j <= ed; j ++)
                    str += string(p2, j);
            } else if (s[i - 1] >= 'a' && s[i + 1] <= 'z') {
                if (p1 == 2) st -= 32, ed -= 32;
                for (char j = st; j <= ed; j ++)
                    str += string(p2, j);
            } else {
                ans += s[i];
                continue;
            }

            if (p1 == 3) str = string(str.size(), '*');
            if (p3 == 2) reverse(str.begin(), str.end());

            ans += str;
        } else {
            ans += s[i];
        }
    }
    ans += s.back();

    cout << ans;

    return 0;
}

I - I 洛谷 - P5657

手玩几个例子后找到规律;

\(n=4,k=13\)为例,\(k\)大于\(2^3\),说明它是由\(n=3\)的格雷码在前面加\(1\)得到的,否则就是在前面加\(0 \dots\)

上述答案为1011,即\(1+011\rightarrow 10 + 11\rightarrow 101+1\),以\(0\sim 2^k - 1\)标号则位置转移关系为\(13 \rightarrow 2 \rightarrow 2 \rightarrow 1\)\(13 \rightarrow (15 - 13) \rightarrow 2 \rightarrow (3 - 2)\)\(13 \rightarrow (2^4-1)-13 \rightarrow 2 \rightarrow (2^2-1)-2\);

即当前位置超过\(2^{k-1}\)时,都应该转换到\(2^k-1-x\)的位置,否则就按照原来的位置;

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	i64 n, k;
	cin >> n >> k;

	string ans = "";
	auto dfs = [&](auto dfs, i64 x, i64 now)->void{
		if (!now) {
			cout << ans << '\n';
			exit(0);
		}
		if (x >= (1ll << (now - 1))) {
			ans += '1';
			dfs(dfs, (1ll << now) - 1 - x, now - 1);
		} else{
			ans += '0';
			dfs(dfs, x, now - 1);
		}
    };

	dfs(dfs, k, n);

	return 0;
}

J - J 洛谷 - P1309

应该是归并排序的典题了,快排回超时,得用归并排序可以手写也可以直接用\(merge\)函数;

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, r, q;
	cin >> n >> r >> q;
	n *= 2, q--;
	vector<array<int, 3>> ans(n), winner(n/2), loser(n/2);
	for (int i = 0; i < n; i ++)
		cin >> ans[i][0], ans[i][1] = i + 1;
	for (int i = 0; i < n; i ++)
		cin >> ans[i][2];

	auto cmp = [&](array<int, 3> &a, array<int, 3> &b) -> bool{
		if (a[0] == b[0]) return a[1] < b[1];
		return a[0] > b[0];
	};

	sort(ans.begin(), ans.end(), cmp);

	while (r --) {
		for (int i = 0; i < n; i += 2) {
			if (ans[i][2] > ans[i + 1][2]) {
				ans[i][0] ++;
				winner[i / 2] = ans[i];
				loser[i / 2] = ans[i + 1];
			} else {
				ans[i + 1][0] ++;
				winner[i / 2] = ans[i + 1];
				loser[i / 2] = ans[i];
			}
		}
		merge(winner.begin(),winner.end(),loser.begin(),loser.end(),ans.begin(),cmp);
	}

	cout << ans[q][1] << '\n';

	return 0;
}
#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, r, q;
	cin >> n >> r >> q;
	n *= 2, q--;
	vector<array<int, 3>> ans(n), winner(n), loser(n);
	for (int i = 0; i < n; i ++)
		cin >> ans[i][0], ans[i][1] = i + 1;
	for (int i = 0; i < n; i ++)
		cin >> ans[i][2];

	auto cmp = [&](array<int, 3> &a, array<int, 3> &b) -> bool{
		if (a[0] == b[0]) return a[1] < b[1];
		return a[0] > b[0];
	};

	sort(ans.begin(), ans.end(), cmp);

	while (r --) {
		for (int i = 0; i < n; i += 2) {
			if (ans[i][2] > ans[i + 1][2]) {
				ans[i][0] ++;
				winner[i / 2] = ans[i];
				loser[i / 2] = ans[i + 1];
			} else {
				ans[i + 1][0] ++;
				winner[i / 2] = ans[i + 1];
				loser[i / 2] = ans[i];
			}
		}
		int m = n / 2;
		int cnta = 0, cntw = 0, cntl = 0;
		while (cntw < m && cntl < m) {
			if (cmp(winner[cntw], loser[cntl])) ans[cnta ++] = winner[cntw ++];
			else ans[cnta ++] = loser[cntl ++];
		}
		while (cntw < m) ans[cnta ++] = winner[cntw ++];
		while (cntl < m) ans[cnta ++] = loser[cntl ++];
	}

	cout << ans[q][1] << '\n';

	return 0;
}

K - K 洛谷 - P2058

题目保证时间递增,可以采用单调队列将不在一天的信息移出去;

维护每艘船的数量,当某艘船数量为0时从答案中移除;

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n;
	cin >> n;
	vector k(n, vector<int>());
	deque<int> time;
	vector<int> num(100010), t(n);
	set<int> ans;
	for (int i = 0; i < n; i ++) {
		int p;
		cin >> t[i] >> p;
		for (int j = 0; j < p; j ++) {
			int x;
			cin >> x;
			k[i].push_back(x);
			num[x] ++;
			ans.insert(x);
		}

		time.push_back(i);
		while (t[time.front()] <= t[i] - 86400) {
			int io = time.front();
			for (auto x : k[io]) {
				if (!--num[x]) ans.erase(x);
			}
			time.pop_front();
		}

		cout << ans.size() << '\n';

	}

	return 0;
}

N - N 洛谷 - P2048

贪心+堆+RMQ;

每段超级和弦都是这段区间里的和,而区间和不难想到前缀和,如果考虑暴力,那么需要将所有满足条件的区间抽出来排序,但是在\(n\)过大时这是难以想象的;

那么对于一个区间,其贡献就是其子区间中和最大的区间,要求出这个最大和,那就是RMQ的问题了,这里可以用ST表求出区间最大的和的下标值,当然一个区间中也有可能有多个区间满足第二大,第三大等等,所以每次取出最大和的区间后应该把区间向两边缩减,例如[1,10]这个区间的最大和的下标在5,但是[1,4]或者[6,10]也可能产生次最大和,所以我们也要考虑进去;

进行贪心的话,可以考虑用一个优先队列放置区间,排序规则就按区间最大和排序;

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

const int N = 5e5 + 10;
i64 sum[N], Cnt[N][20];

void init(int n) {
	for (int i = 1; i <= n; i ++)
		Cnt[i][0] = i;
	for (int j = 1; (1 << j) <= n; j ++) {
		for (int i = 1; i + (1 << j) - 1 <= n; i ++) {
			int x = Cnt[i][j - 1], y = Cnt[i + (1 << (j - 1))][j - 1];
			Cnt[i][j] = sum[x] > sum[y] ? x : y;
		}
	}
}

int query(int l, int r) {
	if (r < l) return INT_MIN;
	int k = log2(r - l + 1);
	int x = Cnt[l][k], y = Cnt[r - (1 << k) + 1][k];
	return sum[x] > sum[y] ? x : y;
}

struct E {
	int o, l, r, t;
	E(int o, int l, int r) : o(o), l(l), r(r), t(query(l, r)) {}
	friend bool operator < (const E& a, const E& b) {
		return sum[a.t] - sum[a.o - 1] < sum[b.t] - sum[b.o - 1];
	}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, k, L, R;
	cin >> n >> k >> L >> R;

	priority_queue<E> Q;
	for (int i = 1; i <= n; i ++) {
		cin >> sum[i];
		sum[i] += sum[i - 1];
	}

	init(n);
	for (int i = 1; i <= n; i ++)
		if (i + L - 1 <= n)
			Q.push({i, i + L - 1, min(i + R - 1, n)});

	i64 ans = 0;
	while (k --) {
		auto [o, l, r, t] = Q.top();
		Q.pop();
		ans += sum[t] - sum[o - 1];
		if (l != t) Q.push({o, l, t - 1});
		if (r != t) Q.push({o, t + 1, r});
	}

	cout << ans << '\n';

	return 0;
}
posted @ 2024-03-21 21:30  Ke_scholar  阅读(4)  评论(0编辑  收藏  举报