Gourmet Grazers平衡树

F - Gourmet Grazers
Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

Like so many others, the cows have developed very haughty tastes and will no longer graze on just any grass. Instead, Farmer John must purchase gourmet organic grass at the Green Grass Grocers store for each of his N (1 ≤ N ≤ 100,000) cows.

Each cow i demands grass of price at least Ai (1 ≤ Ai ≤ 1,000,000,000) and with a greenness score at least Bi (1 ≤ Bi ≤ 1,000,000,000). The GGG store has M (1 ≤ M ≤ 100,000) different types of grass available, each with a price Ci (1 ≤ Ci ≤ 1,000,000,000) and a greenness score of Di (1 ≤ Di ≤ 1,000,000,000). Of course, no cow would sacrifice her individuality, so no two cows can have the same kind of grass.

Help Farmer John satisfy the cows' expensive gourmet tastes while spending as little money as is necessary.

Input

* Line 1: Two space-separated integers: N and M.
* Lines 2..N+1: Line i+1 contains two space-separated integers: Ai and Bi
* Lines N+2..N+M+1: Line i+N+1 contains two space-separated integers: Ci and Di

Output

* Line 1: A single integer which is the minimum cost to satisfy all the cows. If that is not possible, output -1.

Sample Input

4 7
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4

Sample Output

12
 
 
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 100005;
const int MOD = 2147483647;

struct Node
{
     int left;      //左子树
     int right;     //右子树
     int size;      //大小
     int val;       //
     int key;       //平衡种子
     
}tree[MAXN];


struct node{
    int x;
    int y;
    
}a[MAXN],b[MAXN];


bool cmp(node a,node b){
    if(a.y == b.y ){
        return a.x > b.x ;
    }
    return a.y >b.y ;
} 
int root,tot;

int add(int val){
    
    tot++;
    tree[tot].size = 1;
    tree[tot].val = val;
    tree[tot].key = rand()%MOD;
    tree[tot].left = 0;
    tree[tot].right = 0;

    return tot;
}

void update_root(int now){
    int left,right;

    left = tree[now].left;
    right = tree[now].right;

    tree[now].size = tree[left].size + tree[right].size + 1;
}

//拆分(now原treap,a左子树,b右子树,val值)
void split_new(int now, int &a, int &b, int val){
    
    if(now == 0){
        a = 0;
        b = 0;
        return;
    }

    if(tree[now].val <= val){//now左子树中的所有值都小于now,
        a = now;
        split_new(tree[now].right, tree[a].right, b, val);
    }else{
        b = now;
        split_new(tree[now].left, a, tree[b].left, val);
    }

    update_root(now);
}//按权值aplit 

void merge_new(int &now, int a, int b){
    
    if(a==0 || b==0){
        now = a+b;
        return;
    }//某节点为空直接返回另一节点,合并结束 

    //按照key值合并(堆性质)
    if(tree[a].key<tree[b].key){
        /**
         * a树key值小于b树,那么b树属于a树的后代,因为b树恒大于a树,那么b树一定属于a树的右后代,
         * a的左子树不变,直接赋给now,递归合并a的右子树和b
         */
        now = a;
        merge_new(tree[now].right, tree[a].right, b);//b加到a的右后代上,a的右子树与y合并 
         
    }else{
        //a的key值大于b树,b的左子树与a合并 
        now = b;
        merge_new(tree[now].left, a, tree[b].left);
    }

    update_root(now);
}

int find_new(int now, int rank){//找第k大

//    if(rank==0){
//        return 0;
//    }超时原因之一 
    
    while (tree[tree[now].left].size+1 != rank){
        if(tree[tree[now].left].size >= rank){
            now = tree[now].left;
        }else{
            rank -= tree[tree[now].left].size + 1;
            now = tree[now].right;
        }
    }
    return tree[now].val;
    //printf("%d\n", tree[now].val);
}

void insert_new(int val){
    int x,y,z;

    x = 0;
    y = 0;
    z = add(val);
    split_new(root, x, y, val);
    merge_new(x,x,z);
    merge_new(root, x, y);
}

void del_new(int val){
    int x,y,z;

    x = y = z = 0;
    split_new(root, x, y, val);
    split_new(x, x, z, val-1);
    merge_new(z, tree[z].left, tree[z].right);
    merge_new(x, x, z);
    merge_new(root, x, y);
}

int get_next(int val){
    int x,y;

    x = y = 0;
    split_new(root,x,y,val);
    int u=find_new(y,1);
    merge_new(root,x,y);
    return u;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    memset(tree,0,sizeof(tree));

    int s;
    
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].x ,&a[i].y );
    }
    
    for(int j=1;j<=m;j++){
        scanf("%d%d",&b[j].x ,&b[j].y);
    }    
    
    sort(a+1,a+1+n,cmp);
    sort(b+1,b+1+m,cmp);
    
//    for(int i=1;i<=m;i++){
//        printf("%d^^\n",b[i].y );
//    }
    
    long long sum;
    int k=1;
    int u;
    sum=0;
    for(int i=1;i<=n;i++){
        
        while(b[k].y>=a[i].y&&k<=m){
            insert_new(b[k].x);
            k++;
        }    
            
        s=0;
        u=a[i].x;
        u--;
        s=get_next(u);
        if(!s){
            printf("-1\n");
            return 0;
        }
        sum+=s;
        
        del_new(s);
    }    
    printf("%lld",sum);
    return 0;
}

 

posted @ 2022-07-30 16:17  killjoyskr  阅读(19)  评论(0)    收藏  举报