Description
有X+Y+Z个三元组(x[i],y[i],z[i]),请你从每个三元组中挑数,并满足以下条件:
1、每个三元组中可以且仅可以选择一个数(即x[i],y[i],z[i]中的一个)
2、选择x[i]的三元组个数恰好为X
3、选择y[i]的三元组个数恰好为Y
4、选择z[i]的三元组个数恰好为Z问选出的数的和最大是多少
问选出的数的和最大是多少
对于100%的数据满足,1<=X+Y+Z<=500000,0<=x[i],y[i],z[i]<=500000
Solution
- 显然是一道贪心题,但是策略还是挺难想到的。
- 如果只有x和y,我们可以考虑先全部选x,然后找出前y个(y-x)最大的替换掉x。
- 同理,有三个元素,我们也可以考虑全部先选x,先不考虑x的问题。那么只剩下y和z要考虑。
- 如果x的选择已经确定了的话,那么剩下的所有元素就是按照y-z排序,前y个选y了。
- 所以对于所有的元素而言,按照y-z排序,最优方案一定有一个分界,左边的选y和x,右边的选择z和x。
- 对于左边的选择y和x的,同理可以找出前y个(y-x)最大的,注意到当分界点往右移的时候,y这边只会加不会减,那么对于前y个也只会增不会减。根据单调性,在所有元素的按y-x排序的顺序中再用两个指针维护就好了。
- 右边的同理。
- 那么如果我们的排序用的桶排实际上是可以做到O(n)的。
- 偷懒直接快排了。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 500005
#define ll long long
using namespace std;
int nx,ny,nz,n,i,j,k,t,A[maxn],B[maxn],C[maxn],tb[maxn],tc[maxn];
int ly,ry,lz,rz,bz1[maxn],bz2[maxn],bz[maxn];
struct arr{ll x,y,z;} a[maxn];
int cmp1(int i,int j){return a[i].y-a[i].z>a[j].y-a[j].z;}
int cmp2(int i,int j){return a[i].y-a[i].x>a[j].y-a[j].x;}
int cmp3(int i,int j){return a[i].z-a[i].x>a[j].z-a[j].x;}
ll sum,ans;
int read(){
int x=0; char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x;
}
void Max(int &x,int y){x=(x>y)?x:y;}
void Min(int &x,int y){x=(x<y)?x:y;}
int main(){
nx=read(),ny=read(),nz=read();
n=nx+ny+nz;
for(i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].z=read();
for(i=1;i<=n;i++) A[i]=B[i]=C[i]=i;
sort(A+1,A+1+n,cmp1),
sort(B+1,B+1+n,cmp2),
sort(C+1,C+1+n,cmp3);
for(i=1;i<=n;i++) tb[B[i]]=i,tc[C[i]]=i;
ans=sum=0;
ly=n,ry=1;
for(i=1;i<=ny;i++) Min(ly,tb[A[i]]),Max(ry,tb[A[i]]),sum+=a[A[i]].y,bz1[A[i]]=1;
lz=n,rz=1,k=0;
for(i=1;i<=n;i++) if (!bz1[C[i]]&&k<nz) {
bz2[C[i]]=1,k++,Min(lz,tc[C[i]]),Max(rz,tc[C[i]]);
sum+=a[C[i]].z;
} else if (!bz1[C[i]]) sum+=a[C[i]].x;
for(i=1;i<=ny;i++) bz[A[i]]=1;
ans=max(ans,sum);
for(i=ny+1;i<=n-nz;i++) {
bz[A[i]]=1;
if (tb[A[i]]<ly) {
ly=tb[A[i]];
bz1[A[i]]=1;
sum+=a[A[i]].y-a[B[ry]].y+a[B[ry]].x;
bz1[B[ry]]=0;
for(ry--;!bz1[B[ry]];ry--);
} else if (tb[A[i]]<ry){
bz1[A[i]]=1;
sum+=a[A[i]].y-a[B[ry]].y+a[B[ry]].x;
bz1[B[ry]]=0;
for(ry--;!bz1[B[ry]];ry--);
} else sum+=a[A[i]].x;
if (tc[A[i]]==lz){
bz2[A[i]]=0;
sum-=a[A[i]].z;
if (nz>1) for(lz++;!bz2[C[lz]];lz++);
for(rz++;bz[C[rz]];rz++);
if (!bz2[C[lz]]) lz=rz;
sum+=a[C[rz]].z-a[C[rz]].x;
bz2[C[rz]]=1;
} else
if (tc[A[i]]<=rz){
bz2[A[i]]=0;
sum-=a[A[i]].z;
for(rz++;bz[C[rz]];rz++);
sum+=a[C[rz]].z-a[C[rz]].x;
bz2[C[rz]]=1;
} else sum-=a[A[i]].x;
ans=max(ans,sum);
}
printf("%lld",ans);
}