【题解】
将牛和草分别按鲜嫩度从大到小排序
然后将牛扫一遍:
对于第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; }