P10673 【MX-S1-T2】催化剂 题解
前置知识
解法
从贪心的角度分析,当小 K 有 \(x(x \ge k)\) 个同种糖果时,将其分给 \(k\) 个小朋友时尽可能平均发是最优情况,此时产生的愤怒值为 \(x-k\)。
那么,设出现次数 \(\ge k\) 的糖果分别为 \(b_{1},b_{2},b_{3}, \dots ,b_{m}\),其出现次数分别为 \(c_{1},c_{2},c_{3}, \dots ,c_{m}\),最终有 \(\sum\limits_{i=1}^{m}c_{i}-mk\) 即为所求。其中,\(\sum\limits_{i=1}^{m}c_{i}\) 和 \(m\) 均可通过权值树状数组维护。
注意及时删除因修改造成的影响及树状数组中下标为 \(0\) 对操作中的影响。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
ll c[2][3000010],vis[3000010];
ll lowbit(ll x)
{
return x&(-x);
}
void add(ll n,ll x,ll key,ll c[])
{
for(ll i=x;i<=n;i+=lowbit(i))
{
c[i]+=key;
}
}
ll getsum(ll x,ll c[])
{
ll ans=0;
for(ll i=x;i>=1;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
int main()
{
ll n,q,pd,x,i;
scanf("%lld%lld",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%lld",&x);
if(vis[x]!=0)
{
add(3000000,vis[x],-1,c[0]);
add(3000000,vis[x],-vis[x],c[1]);
}
vis[x]++;
if(vis[x]!=0)
{
add(3000000,vis[x],1,c[0]);
add(3000000,vis[x],vis[x],c[1]);
}
}
for(i=1;i<=q;i++)
{
scanf("%lld%lld",&pd,&x);
if(pd==1)
{
if(vis[x]!=0)
{
add(3000000,vis[x],-1,c[0]);
add(3000000,vis[x],-vis[x],c[1]);
}
vis[x]++;
if(vis[x]!=0)
{
add(3000000,vis[x],1,c[0]);
add(3000000,vis[x],vis[x],c[1]);
}
}
if(pd==2)
{
if(vis[x]!=0)
{
add(3000000,vis[x],-1,c[0]);
add(3000000,vis[x],-vis[x],c[1]);
}
vis[x]--;
if(vis[x]!=0)
{
add(3000000,vis[x],1,c[0]);
add(3000000,vis[x],vis[x],c[1]);
}
}
if(pd==3)
{
printf("%lld\n",getsum(3000000,c[1])-getsum(x-1,c[1])-(getsum(3000000,c[0])-getsum(x-1,c[0]))*x);
}
}
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18275566,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。