D - Pair of Balls
模拟
开一个
i
d
id
id 数组,
i
d
[
x
]
[
0
]
id[x][0]
id[x][0] 和
i
d
[
x
]
[
1
]
id[x][1]
id[x][1] 表示编号为
x
x
x 的球所在的桶的编号,每消除一对球,就把球的编号
p
u
s
h
push
push 进队列,通过球的编号找到需要更新的桶的编号
#include<bits/stdc++.h>
#define ll long long
#define _ 0
using namespace std;
const int maxn = 2e5 + 9;
ll n, m, x, y;
struct node
{
vector <int> v;
int pos;
}a[maxn];
vector <int> id[maxn];
queue <int> q;
int ans, now;
void work()
{
cin >> n >> m;
for(int i = 1; i <= m; ++i)
{
int k;cin >> k;
for(int j = 1; j <= k; ++j)
{
int p;cin >> p;a[i].v.push_back(p);
if(j == 1) id[p].push_back(i);
if(id[p].size() == 2) q.push(p);
}
}
while(!q.empty())
{
now = q.front(); q.pop();
ans += 2;
int x = id[now][0];
++a[x].pos;
if(a[x].pos < a[x].v.size())
{
int p = a[x].v[a[x].pos];
id[p].push_back(x);
if(id[p].size() == 2) q.push(p);
}
int y = id[now][1];
++a[y].pos;
if(a[y].pos < a[y].v.size())
{
int p = a[y].v[a[y].pos];
id[p].push_back(y);
if(id[p].size() == 2) q.push(p);
}
}
if(ans == 2 * n) cout << "Yes\n";
else cout << "No\n";
}
int main()
{
ios::sync_with_stdio(0);
work();
return ~~(0^_^0);
}
先二分找到最小的
x
x
x,使得
>
x
>x
>x 的数最后减到
x
x
x。
然后直接用大根堆模拟,来暴力选取后面的数,因为去掉上面的数之后,至多只剩下
n
n
n 轮选择,所以复杂度是对的
只剩下不超过
n
n
n 轮的原因:如果最后剩下的次数超过
n
n
n,那么二分时的
m
i
d
mid
mid 可以再次左移,使得现在的
x
−
1
x-1
x−1,这与二分已经结束矛盾。
#include<bits/stdc++.h>
#define ll long long
#define _ 0
using namespace std;
const int maxn = 2e5 + 9;
ll n, m, k;
ll a[maxn];
bool check(ll mid)
{
ll sum = 0;
for(int i = 1; i <= n; ++i) if(a[i] >= mid)
sum += a[i] - mid;
return sum <= k;
}
ll get()
{
ll l = 0, r = 0;
for(int i = 1; i <= n; ++i) r = max(r, a[i]);
while(l < r)
{
ll mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
void work()
{
cin >> n >> k;
for(int i = 1; i <= n; ++i) cin >> a[i];
ll lim = get(), ans = 0, num = 0;
for(int i = 1; i <= n; ++i) if(a[i] >= lim)
{
num += a[i] - lim;
ans += (a[i] - lim) * (a[i] + lim + 1) / 2ll;
a[i] = lim;
}
priority_queue <ll> q;
for(int i = 1; i <= n; ++i) q.push(a[i]);
for(ll i = num + 1; i <= k; ++i)
{
ll now = q.top();q.pop();
if(now <= 0) break;
ans += now;
q.push(now - 1);
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(0);
work();
return ~~(0^_^0);
}