就按照题意建出有向图来(n个点,2n-2条边),然后从按随便一个rating排序,从最后一个开始dfs,用vis数组防止重复访问,因为每次之前的肯定能访问之后的(及之后的能访问的),所以不会有重复。就行了。
#include<cstdio> #include<algorithm> using namespace std; #define N 100010 int a[N],b[N],A[N],n,B[N],sum; bool cmp(const int &a,const int &b) { return A[a]>A[b]; } bool cm2(const int &a,const int &b) { return B[a]>B[b]; } int e,v[N<<1],next[N<<1],first[N]; void AddEdge(int U,int V) { v[++e]=V; next[e]=first[U]; first[U]=e; } bool vis[N]; void dfs(int U) { ++sum; vis[U]=1; for(int i=first[U];i;i=next[i]) if(!vis[v[i]]) dfs(v[i]); } int anss[N]; int main() { freopen("codecoder.in","r",stdin); freopen("codecoder.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d%d",&A[i],&B[i]); for(int i=1;i<=n;++i) a[i]=b[i]=i; sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cm2); for(int i=1;i<n;++i) AddEdge(a[i],a[i+1]); for(int i=1;i<n;++i) AddEdge(b[i],b[i+1]); for(int i=n;i>=1;--i) { if(!vis[a[i]]) dfs(a[i]); anss[a[i]]=sum-1; } for(int i=1;i<=n;++i) printf("%d ",anss[i]); return 0; }