bzoj1691: [Usaco2007 Dec]挑剔的美食家

按價格講草和牛排序,維護一個以美味度爲關鍵字的平衡樹,不斷枚舉牧草,插入比牧草價值低的牛,之後用平衡樹選擇前驅並刪除。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    char ch=getchar();int f=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {f=f*10+(ch^48);ch=getchar();}
    return f;
}
int ch[200005][2],w[200005],fa[200005];
struct data
{
    int val;
    int sum;
}a[100005],b[100005];
bool cmp(const data &x,const data &y)
{
    if(x.val!=y.val)
    return x.val<y.val;
    return x.sum<y.sum;
}
int n,m,rt,t,cou,sz;
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y],l,r;
    if(ch[y][0]==x) l=0;else l=1;r=l^1;
    if(y==k)
    {
        k=x;
    }
    else
    {
        if(ch[z][0]==y) ch[z][0]=x;
        else ch[z][1]=x;
    }
    fa[x]=z,fa[y]=x,fa[ch[x][r]]=y;
    ch[y][l]=ch[x][r];ch[x][r]=y;
}
void splay(int x,int &k)
{
    int y,z;
    while(x!=k)
    {
        y=fa[x];z=fa[y];
        if(y!=k)
        {
            if(ch[y][0]==x^ch[z][0]==y) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void insert(int &k,int x,int last)
{
    if(!k)
    {
        k=++sz;
        w[k]=x;
        fa[k]=last;
        splay(k,rt);
        return;
    }
    if(x<=w[k]) insert(ch[k][0],x,k);
    else insert(ch[k][1],x,k);
}
long long ans;
void ask_before(int x,int k)
{
    if(!k) return;
    if(w[k]<=x)
    {
        t=k;
        ask_before(x,ch[k][1]);
    }
    else
    ask_before(x,ch[k][0]);
}
void del(int x)
{
    splay(x,rt);
    if(!ch[x][0]) rt=ch[x][1];
    else if(!ch[x][1]) rt=ch[x][0];
    else
    {
        int k=ch[x][1];
        while(ch[k][0])
        k=ch[k][0];
        ch[k][0]=ch[x][0];
        fa[ch[x][0]]=k;
        rt=ch[x][1];
    }
    fa[rt]=0;
    return;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        a[i].val=read();a[i].sum=read();
    }
    for(int i=1;i<=m;i++)
    {
        b[i].val=read();b[i].sum=read();
    }
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+m+1,cmp);

    int now=1;
    for(int i=1;i<=m;i++)
    {
        while(a[now].val<=b[i].val&&now<=n)
        {
            insert(rt,a[now].sum,0);
            now++;
        }
        t=0;
        ask_before(b[i].sum,rt);
        if(t)
        {
            cou++;
            ans+=b[i].val;
            if(cou==n)
            break;
            del(t);
        }
    }
    if(cou!=n)
    puts("-1");
    else printf("%lld",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章