看似花里胡哨实则是道纯贪心(水题);
n 不会超过 1e5,则上下界越线一定存在 0 解;小于1e5 可枚举一轮是否有未出现的;
抽屉原理计算每个数拿到最少情况下的数量、最少情况下共拿了多少、最少情况下拿了多少不是自己的数字;
从而计算从最少量到目标量( len 需等于该数)可以白嫖多少,剩下的需要额外贡献;
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
const int max_n=1e5+5;
int m,dff,sl,sr;
int a[max_n],c[max_n];
map<int,int>mtmp;
map<int,int>mrmp;
map<int,int>mnmp;
map<int,int>mp;
void clear()
{
mnmp.clear();
mtmp.clear();
mrmp.clear();
mp.clear();
dff=0,sl=0,sr=0;
}
void solve()
{
clear();
cin>>m;
for(int i=1;i<=m;i++){
int n,l,r,sum=0;cin>>n>>l>>r;
dff+=r-l;sl+=l;sr+=r;
for(int i=1;i<=n;i++){cin>>a[i];mp[a[i]]+=r;}
for(int i=1;i<=n;i++){
cin>>c[i];
sum+=c[i];
}
for(int i=1;i<=n;i++){
mnmp[a[i]]+=max(0LL,l-(sum-c[i]));
mtmp[a[i]]+=max(0LL,sum-c[i]-l);
mrmp[a[i]]+=max(sum-c[i],l);
}
}
if(dff>max_n){
cout<<0<<endl;
return;
}
for(int i=sl;i<=sr;i++){
if(mp[i]==0){
cout<<0<<endl;
return;
}
}
int ans=1e18;
for(auto mi:mp){
int tem=mi.fi;
if(tem>=sl&&sr>=tem){
ans=min(ans,mnmp[tem]+max(0LL,tem-mrmp[tem]-(sr-mp[tem]+mtmp[tem])));
}
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _t;cin>>_t;
while(_t--){
solve();
}
return 0;
}
(其实有个 bug 我不知道算不算,sl 和 sr 会超1e18的吧,求大佬解答)