CodeForces 749D Leaving Auction

二分查找,$set$。

对于某一次询问,如果把人删光了,那么输出$0$ $0$。

如果只剩下$1$个人,那么输出那个人喊的最低价格。

如果剩下的人数有大于等于两个,

这时最底下出现的情景必然是红色部分由一个人喊,紫色部分由另一个人喊。

这两个人分别是喊价最高价次高者和最高者,并且红色部分最后一个位置的下一个位置就是答案。因此只需在获取两个人的信息后,在最高者喊价序列中二分即可。

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;

const int maxn=200010;
int n,q;

struct X
{
    int id,val;
}s[maxn];

struct XX{
    int a,b;
    XX () { }
    XX(int A,int B)
    {
        a=A;
        b=B;
    }

    bool operator < (const XX &aa) const
    {
        return b>aa.b;
    }
};

XX fir,sec;

vector<int> v[maxn];
set<XX> h;

int tmp[maxn],mn[maxn],mx[maxn];

bool check(int x)
{
    int tt=v[fir.a][x];
    if(s[tt].val<sec.b) return 0;
    return 1;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=200000;i++) mx[i]=0,mn[i]=2000000000;

    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&s[i].id,&s[i].val);
        v[s[i].id].push_back(i);
        mx[s[i].id]=max(mx[s[i].id],s[i].val);
        mn[s[i].id]=min(mn[s[i].id],s[i].val);
    }

    for(int i=1;i<=200000;i++)
    {
        if(mx[i]==0) continue;
        h.insert(XX(i,mx[i]));
    }

    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        int k; scanf("%d",&k);
        for(int j=1;j<=k;j++) scanf("%d",&tmp[j]);
        for(int j=1;j<=k;j++)
        {
            if(mx[tmp[j]]==0) continue;
            h.erase(XX(tmp[j],mx[tmp[j]]));
        }

        if(h.size()==0)
        {
            printf("0 0\n");
        }
        else if(h.size()==1)
        {
            XX ans = *h.begin();
            printf("%d %d\n",ans.a,mn[ans.a]);
        }
        else
        {
            set<XX>::iterator iter;
            int cnt=0;

            for(iter = h.begin() ; iter != h.end(); iter++)
            {
                cnt++;
                if(cnt==1) fir = *iter;
                else if(cnt==2)  {  sec = *iter; break;  }
            }

            int L=0,R=v[fir.a].size()-1;
            int ans;

            while(L<=R)
            {
                int mid=(L+R)/2;
                if(check(mid)) ans=mid,R=mid-1;
                else L=mid+1;
            }

            int tt=v[fir.a][ans];
            printf("%d %d\n",s[tt].id,s[tt].val);

        }

        for(int j=1;j<=k;j++)
        {
            if(mx[tmp[j]]==0) continue;
            h.insert(XX(tmp[j],mx[tmp[j]]));
        }
    }
    return 0;
}

 

posted @ 2016-12-27 09:22  Fighting_Heart  阅读(247)  评论(0编辑  收藏  举报