首先对于所有的奶牛和草堆按照鲜嫩度排序,这样倒着枚举奶牛,动态插入所有大于等于当前美味度的草堆,这样在treap中维护的所有的节点都是合法的,然后就可以贪心的去找后继了。贪心的证明比较简单就不说了
BZOJ上不能使用ctime函数库,但是不初始化种子的话特别容易挂,所以随便相乘取一下质数的mod就好了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#define LL long long
#define maxn 100020
#include<algorithm>
using namespace std;
int n,m;LL ans;
typedef pair<int,int>pii;
pii gra[maxn],cow[maxn];
struct Tree{
int r,x,size;
Tree* ch[2];
Tree(int a,int b,Tree* c=NULL,Tree* d=NULL){
r=a,x=b,ch[0]=c,ch[1]=d,size=1;
}
};
Tree* rt=NULL;//0 左 1 右
void Rotate(Tree* &u,int d){
Tree* v=u->ch[!d];u->ch[!d]=v->ch[d],v->ch[d]=u;
u=v;
}
void insert(Tree* &u,int x){
if(u==NULL){
u=new Tree(rand(),x,NULL,NULL);
return;
}
if(u->x==x){
u->size++;return;
}int d;
if(x>u->x){
insert(u->ch[d=1],x);
}else insert(u->ch[d=0],x);
if(u->ch[d]->r > u->r)Rotate(u,!d);
}
int last;
int find(Tree* u,int x){
if(u==NULL)return last;
if(u->x==x)return x;
int d=x>u->x;
if(d==1)return find(u->ch[d],x);
else {
last=u->x;
return find(u->ch[d],x);
}
}
void remove(Tree* &u,int x){
if(u->x==x){
if(u->size>1){u->size--;return;}
if(u->ch[0]==NULL)u=u->ch[1];
else if(u->ch[1]==NULL)u=u->ch[0];
else{
if(u->ch[0]->r>u->ch[1]->r){
Rotate(u,1);remove(u->ch[1],x);
}else {
Rotate(u,0);remove(u->ch[0],x);
}
}
}else remove(u->ch[(x>u->x)],x);
}
void solve(){
int r=m;
for(int x,c,d,i=n;i>=1;i--){
d=cow[i].first,c=cow[i].second;
while(r>0&&d<=gra[r].first)insert(rt,gra[r].second),r--;
if(rt==NULL){puts("-1");return;}
x=find(rt,c);
if(x==-1){puts("-1");return;}
ans+=(LL)x;
remove(rt,x);
}
printf("%lld",ans);
}
int main(){
scanf("%d%d",&n,&m);
srand(n%2333*(m%2333)%2333);
for(int i=1;i<=n;i++){
scanf("%d%d",&cow[i].second,&cow[i].first);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&gra[i].second,&gra[i].first);
}
sort(cow+1,cow+1+n);sort(gra+1,gra+1+m);
solve();
return 0;
}