E - Least Elements (atcoder.jp)
(1)题目大意
给你一个长度为N的序列A,并且两个整数M和K,连续M个里面前K小的数的和。
(2)解题思路
考虑用multiset进行模拟,定义两个multiset,mt1表示维护前k个最小的,mt2表示剩下的m-k个,然后用个s维护mt1里面的数的和,每次pop掉一个下标下雨i-m的数。
(3)代码实现
#include "bits/stdc++.h"
#define rep(i, z, n) for (int i = z; i <= n; i++)
#define per(i, n, z) for (int i = n; i >= z; i--)
#define ll long long
#define db double
#define PII pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 2e5 + 10;
ll a[N];
void solve()
{
multiset<ll> mt1, mt2;
ll s = 0;
int n, m, k;
cin >> n >> m >> k;
rep(i, 1, n) cin >> a[i];
rep(i, 1, m) mt1.insert(a[i]), s += a[i];
while (mt1.size() > k)
{
ll v = *(--mt1.end());
mt1.erase((--mt1.end()));
s -= v;
mt2.insert(v);
}
vector<ll> ans;
ans.push_back(s);
rep(i, m + 1, n)
{
ll last = *(--mt1.end());
if (a[i] > last)
mt2.insert(a[i]);
else
mt1.insert(a[i]), s += a[i];
if (mt1.find(a[i - m]) != mt1.end())
{
s -= a[i - m];
mt1.erase(mt1.find(a[i - m]));
}
else
{
mt2.erase(mt2.find(a[i - m]));
}
while (mt1.size() > k)
{
ll v = *--mt1.end();
mt2.insert(v);
s -= v;
// cout << "1:" << i << ',' << v << endl;/
mt1.erase(--mt1.end());
}
while (mt1.size() < k)
{
ll v = *(mt2.begin());
mt1.insert(v);
s += v;
// cout << "2:" << i << ',' << v << endl;
mt2.erase(mt2.begin());
}
ans.push_back(s);
}
for (auto x : ans)
cout << x << ' ';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
while (T--)
solve();
return 0;
}
F - Xor Minimization (atcoder.jp)
(1)题目大意
给你一个长度为N的序列A,让你找出一个x,使得异或每一个A[i]后的M的最大值最小,让你输出这个M是多少。
(2)解题思路
考虑字典树预处理出每一个数的30位,然后dfs从最高位开始,若当前位不存在0,那我们往1走,若不存在1,那我们往0走,若两个都存在则我们选择从0走或者从1走取个最小值加上当前1<<f(f表示当前是第几位)就可以。
(3)代码实现
// Problem: F - Xor Minimization
// Contest: AtCoder - AtCoder Beginner Contest 281
// URL: https://atcoder.jp/contests/abc281/tasks/abc281_f
// Memory Limit: 1024 MB
// Time Limit: 2500 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include "bits/stdc++.h"
#define rep(i, z, n) for (int i = z; i <= n; i++)
#define per(i, n, z) for (int i = n; i >= z; i--)
#define ll long long
#define db double
#define PII pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 2e5 + 10;
int seg[N * 30][2], a[N], idx;
void insert(int x)
{
int p = 0;
for (int i = 29; i >= 0; i--)
{
int to = x >> i & 1;
if (!seg[p][to])
{
seg[p][to] = ++idx;
}
p = seg[p][to];
}
}
int dfs(int f, int root, int num)
{
if (f == -1)
{
return 0;
}
if (!seg[root][1])
{
return dfs(f - 1, seg[root][0], num);
}
else if (!seg[root][0])
{
return dfs(f - 1, seg[root][1], num);
}
else
{
return (1 << f) + min(dfs(f - 1, seg[root][0], num), dfs(f - 1, seg[root][1], num));
}
}
void solve()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
insert(a[i]);
}
cout << dfs(29, 0, 0) << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
while (T--)
solve();
return 0;
}