Buy One, Get One Free
Problem solution
First of all, if it has no requirements and can only choose strictly less than as a gift, I think it should be easy for us to think of a greedy strategy of choosing one after the other.
But obviously, under the strict requirements, we can't do so and consider going back on our greed.
We can reduce gifts with the same price into one category and deal with them one by one. Obviously, gifts in the same category cannot be established
B
u
y
−
G
e
t
Buy-Get
Buy − Get relationship.
If we had
B
u
y
Buy
Buy's gift ratio
G
e
t
Get
Get has a lot of gifts. It's obvious that we can go directly now
G
e
t
Get
Get gift.
If we can't now
G
e
t
Get
Get, at this time, we have to consider whether to buy these gifts or the front
G
e
t
Get
Buy some gifts from Get and go again
G
e
t
Get
Get these gifts.
This can obviously be solved by turning back on greed.
It is obvious that one time of repentance will increase
2
2
2 places for
G
e
t
Get
Get the number of gifts, that is, the number of gifts we are currently processing
+
2
+2
+2, and
B
u
y
Buy
Buy gift will also bring us one
G
e
t
Get
Get quota so that we can handle the number of gifts
+
2
+2
+2.
If our current minimum cost of reneging
x
⩽
2
v
a
l
i
x\leqslant 2val_{i}
x ⩽ 2vali is equivalent to the treatment after we renege. The cost of these two same gifts is lower. We renege and add these two to the answer. Obviously, the cost of these two reneges is
2
v
a
l
i
−
x
2val_{i}-x
2vali − x, and if we go back on the previous one, we can also go back on it again
x
x
x. So we're going to add both to the heap.
The price of our repudiation is to find the smallest one at a time, which can be maintained through the smallest heap.
However, the above estoppel is when we have two identical values, but we may encounter a situation where the current value is only one number. In this case, if our
x
⩽
v
a
l
i
x\leqslant val_{i}
x ⩽ vali, we can also go back through repentance
G
e
t
Get
Get the next one, which will add one to us
G
e
t
Get
Get the quota, which is still the optimal method.
So we have to deal with the above two cases.
Just the estoppel cost of the priority queue maintenance.
Time complexity O ( n log n ) O\left(n\log\,n\right) O(nlogn).
Source code
#include<bits/stdc++.h> using namespace std; #define MAXN 500005 #define lowbit(x) (x&-x) #define reg register #define pb push_back #define mkpr make_pair #define fir first #define sec second typedef long long LL; typedef unsigned long long uLL; const int INF=0x3f3f3f3f; const int mo=998244353; const int inv2=499122177; const int jzm=2333; const int zero=10000; const int orG=3,invG=332748118; const double Pi=acos(-1.0); const double eps=1e-5; typedef pair<LL,int> pii; template<typename _T> _T Fabs(_T x){return x<0?-x:x;} template<typename _T> void read(_T &x){ _T f=1;x=0;char s=getchar(); while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();} while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();} x*=f; } template<typename _T> void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');} LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);} int add(int x,int y,int p){return x+y<p?x+y:x+y-p;} void Add(int &x,int y,int p){x=add(x,y,p);} int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;} int n,a[MAXN],b[MAXN],cnt[MAXN],tot,now,sta[MAXN],stak,sum;LL ans; priority_queue<int,vector<int>,greater<int> >q; signed main(){ read(n);for(int i=1;i<=n;i++)read(a[i]),b[++tot]=a[i],ans+=a[i]; sort(b+1,b+tot+1);tot=unique(b+1,b+tot+1)-b-1; for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+tot+1,a[i])-b,cnt[a[i]]++; for(int i=tot;i>0;i--){ now=sum-2*q.size();sum+=cnt[i]; while(now&&cnt[i])now--,cnt[i]--,sta[++stak]=b[i]; while(!q.empty()&&cnt[i]>0) if(q.top()>=b[i]){ if((cnt[i]^1)&&b[i]+b[i]>=q.top()) sta[++stak]=b[i]+b[i]-q.top(); sta[++stak]=q.top(); q.pop();cnt[i]-=2; } else{ sta[++stak]=b[i]; if(cnt[i]^1)sta[++stak]=b[i]; q.pop();cnt[i]-=2; } while(cnt[i]>0)cnt[i]--; while(stak)q.push(sta[stak--]); } while(!q.empty())ans-=q.top(),q.pop(); printf("%lld\n",ans); return 0; }