ZOJ Monthly, July 2015-H

zjhl2 posted @ 2015年7月26日 01:43 , 309 阅读

这题先把边按起点排序,再把询问排序,从大到小处理询问,并且不断加入需要的边,保存终点的最大值和次大值,询问点-次大值就是该询问的答案。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<functional>
#include<vector>
using namespace std;
int team[5],tail,i,j,n,q,m,node[50005],a[50005],ans[50005];
struct rec
{
    int x,y;
}edg[50005];
bool cmp1(int i,int j){return a[i]<a[j];}
bool cmp2(rec a,rec b){return a.x<b.x;}
void add(int i)
{
    if (tail==0){team[++tail]=edg[i].y;return;}
    if (tail==1)
    {
        team[++tail]=edg[i].y;
        if (team[2]<team[1]){int t=team[1]; team[1]=team[2];team[2]=t;}
        return;
    }
    if (edg[i].y<team[2]) team[2]=edg[i].y;
    if (team[2]<team[1]){int t=team[1]; team[1]=team[2];team[2]=t;}
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&q))
    {
        for (i=1;i<=m;i++) scanf("%d%d",&edg[i].x,&edg[i].y);
        for (i=1;i<=q;i++) scanf("%d",&a[i]),node[i]=i;
        sort(node+1,node+q+1,cmp1);
        sort(edg+1,edg+m+1,cmp2);
        j=m; tail=0; memset(ans,0,sizeof(ans));
        for (i=q;i>=1;i--)
        {
            int now=a[node[i]];
            while(j>=0&&edg[j].x>=now) add(j),j--;
            while(tail>0&&team[tail]>now) tail--;
            if (tail==2) ans[node[i]]=now-team[tail];
        }
        for (i=1;i<=q;i++) printf("%d\n",ans[i]);
    }
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter