天天看点

Gym 101142C CodeCoder vs TopForces (搜索+图论)

题目链接:http://codeforces.com/gym/101142/attachments

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))

#define pii pair<ll,ll>
#define mk(x,y) make_pair(x,y)

const int  maxn =1e6+5;
const int mod=1e9+7;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}

/*
题目大意:每个人有个二维标记,
然后每个人的排名可以自己规定,
其大小关系可以拟定为:其中任意一个维度的大小关系。
问每个人心中认为的最高排名是多少。

这道题刚开始想的是简单的容斥,后来想图中
可以产生环的情况,那么就必须建图。
建图方法就是两个维度分别排序加边即可,
加边只用加相邻的边即可。

然后拟定一个顺序,即前面出现的所有排名都可以成为
当前位置的人的排名的一部分,这样答案必定是递增的。
假设有个序列a以j为终点,有个序列b以k为终点,
那么对于扫描到的p,其肯定是可以把前面的序列全部按序排变成自己的排名的,
所以这种顺序下的搜索其只需要不断探索之前未达到过的点并累加当前答案即可。

时间复杂度O(n).

*/

struct node{
    int x,y,id;
}a[maxn];
struct ee{
    int u,nxt;
}e[maxn<<1];
int head[maxn<<1],tot;
void init()
{
    mst(head,-1),tot=0;
}
void add(int x,int y)
{
    e[tot]=ee{y,head[x]};
    head[x]=tot++;
}

bool cmp1(node p,node q)
{
    return p.x>q.x;
}
bool cmp2(node p,node q)
{
    return p.y>q.y;
}
bool cmp3(node p,node q)
{
    return p.x<q.x;
}

int res=0,vis[maxn];
void dfs(int x)
{
    if(vis[x]==0) res++;
    vis[x]=1;
    for(int i=head[x];~i;i=e[i].nxt)
    {
        int v=e[i].u;
        if(vis[v]==0) dfs(v);
    }
}

int ans[maxn],n;

int main()
{
    freopen("codecoder.in","r",stdin);
    freopen("codecoder.out","w",stdout);
    scanf("%d",&n);
    rep(i,0,n){
        scanf("%d%d",&a[i].x,&a[i].y);
        a[i].id=i;///
    }
    init();
    sort(a,a+n,cmp1);
    rep(i,0,n-1) add(a[i].id,a[i+1].id);
    sort(a,a+n,cmp2);
    rep(i,0,n-1) add(a[i].id,a[i+1].id);

    sort(a,a+n,cmp3);
    rep(i,0,n)
    {
        dfs(a[i].id);
        ans[a[i].id]=res;
    }
    rep(i,0,n) printf("%d\n",ans[i]-1);
    return 0;
}
           

继续阅读