기술
X + Y + Z를 갖는 트리플 (X [i]를, Y는 [ I], Z는 [I]), 각 트리플렛에서 선택되는 수의, 다음의 조건이 충족된다 :
(1) 각각의 트리플렛 그룹이 선택 될 수 있으며, 단지 다수의 (즉, X [I], Y [I ], Z는 A [I]을 투입)
2 x가 [I] 정확히 X- 인 트리플의 수를 선택
. 3 선택 Y [ I] 트리플의 수가 정확히 Y이고
Z가 [I] 정확히 Z의 개수 트리플의 수를 선택하는, (4). Q는 가장 많은 선택되는
Q 및 상기 선택된 개수가 최대 개수
입력
처음 세 개의 라인은 음이 아닌 정수의 X, Y는 Z 나타내는
다음 X + Y + Z 세 개의 라인 각각은 음이 아닌 정수 트리플 설명 (X [i]를, Y가 [ I], Z가 [I] )
산출
라인과 선택된 정수는 가장 큰 수이다
샘플 입력
입력 1 :
1 2 1
2 4 4
. 3 2 1
. 7. 제 7
. 5 2 3
입력 2
. 3 2 3
17 1 16
2 7 5
2 12 16이다
. 제 7 7
13 2 10
12 18은 3.
16 15 19
5 6 2.
샘플 출력
출력 1 :
18는
출력 2 :
110
데이터 제약
데이터 만족, 10 %가 1 <= X + Y + Z <= 15
데이터 만족의 30 % 1 <= X + Y + Z <= 100
데이터 만족의 다른 10 %, X = 0
, 다른 20 데이터 만족 %의 트라이어드 모든 x [I] = 0
데이터 만족의 다른 20 %가 1 <= X + Y + Z <= 100000
데이터 만족의 100 %까지 1 <= X + Y + Z <= 500000,0 <= X의 [ I], Y [i]를, Z [I]는 <= 500000
경기
직접 삼십분 초.
10 % 생각 갑자기 직접 모든 Y 마법 중에서 선택된 방법을 생각하고 YZ 정렬 최소 Z로부터 선택 될 수있다.
완벽한 솔루션입니다.
그런 다음이 20 %, 바보 같은 10 % 남아 같은 욕심이 될 수 있다고 생각 생각.
그러나, 그것은 끊었 보인다.
아직 너무 요리.
문제 해결
문제의 해결 방법은 읽을 수 없습니다?
인터넷은 마법의 스택 접근 방식을 가지고에 그것은 감동.
차이는 생각의 사용이다.
모든 YX, ZX 우선, 삼중 사례의 20 % 때문에 추가된다.
20 분 이렇게하려면?
때문에 일부 그룹은 약간의 두통, 수 없습니다.
그러나! 몇 가지 유용한 힙의 특성! !
첫째, 같은 YZ 종류에 따라.
세트 \는 (ansy _ {[I] } \) 전방의 내부 i 번째, Y-Y 상기 선택된 최대 값을 나타낸다.
세트 (\ ansz _ {[I]를 } \) 의 Z Z의 선택된 최대 값을 내부의 i 번째를 나타낸다.
모두 당신이 솔루션을 완성 할 수 물건을 유지하기 위해 힙을 사용 -
최종 해답 + \합니다 (X-SUM \ \) 로
표준 프로세스
단어를 많이보다 빠른 힙이 포효입니다 이후로, 로그 실행 로그 지참하지 않았다.
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
const int maxn=500010;
struct node{
long long x,y,z;
};
node a[maxn];
long long X,Y,Z,x[maxn],y[maxn],z[maxn],tot,d[maxn];
long long ansy[maxn],ansz[maxn],answer,sum;
__attribute__((optimize("-O3")))
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
__attribute__((optimize("-O3")))
void qsort(int l,int r)
{
int i=l;int j=r;
int m=a[(i+j)/2].x;
while (i<=j)
{
while (a[i].x>m) i++;
while (a[j].x<m) j--;
if (i<=j)
{
swap(a[i],a[j]);
i++;j--;
}
}
if (l<j) qsort(l,j);
if (r>i) qsort(i,r);
}
__attribute__((optimize("-O3")))
void up(int x)
{
while (x>1 && d[x/2]>d[x])
{
swap(d[x/2],d[x]);
x/=2;
}
}
__attribute__((optimize("-O3")))
void down(int x)
{
int mb=0;
while (x<tot)
{
if (x*2<=tot)
{
if (x*2+1<=tot)
{
if (d[x*2]>d[x*2+1]) mb=x*2+1; else mb=x*2;
}
else
{
mb=x*2;
}
}
else break;
if (d[x]>d[mb])
{
swap(d[x],d[mb]);x=mb;
}
else break;
}
}
int main()
{
freopen("triple.in","r",stdin);
freopen("triple.out","w",stdout);
scanf("%lld%lld%lld",&X,&Y,&Z);
for (int i=1;i<=X+Y+Z;i++)
{
x[i]=read();y[i]=read();z[i]=read();
sum+=x[i];
a[i].y=y[i]-x[i];
a[i].z=z[i]-x[i];
a[i].x=a[i].y-a[i].z;
}
qsort(1,X+Y+Z);
tot=0;
for (int i=1;i<=Y;i++)
{
d[++tot]=a[i].y;
up(tot);
ansy[Y]+=a[i].y;
}
int n=X+Y+Z;
for (int i=Y+1;i<=n;i++)
{
ansy[i]=ansy[i-1];
if (d[1]<a[i].y)
{
ansy[i]=ansy[i]-d[1]+a[i].y;
d[1]=a[i].y;
down(1);
}
}
tot=0;
for (int i=n;i>=n-Z+1;i--)
{
d[++tot]=a[i].z;
up(tot);
ansz[n-Z+1]+=a[i].z;
}
for (int i=n-Z;i>=1;i--)
{
ansz[i]=ansz[i+1];
if (d[1]<a[i].z)
{
ansz[i]=ansz[i]-d[1]+a[i].z;
d[1]=a[i].z;
down(1);
}
}
answer=0;
for (int i=Y;i<=n-Z;i++)
{
answer=max(answer,sum+ansy[i]+ansz[i+1]);
}
printf("%lld\n",answer);
}