【題解】
將牛和草分別按鮮嫩度從大到小排序
然後將牛掃一遍:
對於第i頭牛,將鮮嫩度>=b[i]的草的價格加入平衡樹,找出價格>=a[i]的最小的草,計入答案並刪除之
正確性分析:若i<j,則i與j的草交換後,答案不會更優
【代碼】
#include<stdio.h>
#include<stdlib.h>
#define INF 2000000000
typedef long long LL;
int a[100005],b[100005],c[100005],d[100005];
LL ans=0;
int min(int a,int b)
{
if(a<b) return a;
return b;
}
void jh(int* a,int* b)
{
int t=*a;
*a=*b;
*b=t;
}
struct Node
{
Node* ch[2];
int v,r;
int cmp(int x) const
{
if(x==v) return -1;
if(x<v) return 0;
return 1;
}
};
Node *root,*null;
void init()
{
null=new Node();
null->ch[0] = null->ch[1] = NULL;
null->v=null->r=0;
root=null;
}
void xz(Node* &o,int d)
{
Node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o=k;
}
void tj(Node* &o,int x)
{
int d=o->cmp(x);
if(o==null)
{
o=new Node();
o->ch[0]=o->ch[1]=null;
o->v=x;
o->r=rand();
return;
}
if(d==-1) d=0;
tj(o->ch[d],x);
if( o->ch[d]->r < o->r ) xz(o,d^1);
}
int cx(Node* &o,int x)
{
int d=o->cmp(x);
if(o==null) return INF;
if(d==-1) return o->v;
if(d==1) return cx(o->ch[d],x);
return min(o->v,cx(o->ch[d],x));
}
void sc(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-1)
{
if(o->ch[0]==null) o=o->ch[1];
else
{
if(o->ch[1]==null) o=o->ch[0];
else
{
if( o->ch[0]->r < o->ch[1]->r ) d=0;
else d=1;
xz(o,d^1);
sc(o->ch[d^1],x);
}
}
}
else sc(o->ch[d],x);
}
void kp(int a[],int b[],int low,int high)
{
int i=low,j=high,mid=a[(i+j)/2];
while(i<j)
{
while(a[i]>mid) i++;
while(a[j]<mid) j--;
if(i<=j)
{
jh(&a[i],&a[j]);
jh(&b[i],&b[j]);
i++;
j--;
}
}
if(j>low) kp(a,b,low,j);
if(i<high) kp(a,b,i,high);
}
int main()
{
srand(325);
int n,m,i,j=1,t;
init();
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
for(i=1;i<=m;i++)
scanf("%d%d",&c[i],&d[i]);
kp(b,a,1,n);
kp(d,c,1,m);
for(i=1;i<=n;i++)
{
while(j<=m&&d[j]>=b[i])
{
tj(root,c[j]);
j++;
}
t=cx(root,a[i]);
if(t==INF) break;
ans+=(LL)t;
sc(root,t);
}
if(i>n) printf("%lld",ans);
else printf("-1");
return 0;
}