CodeCoder vs TopForces
题目链接:
https://codeforc.es/gym/101142
Description
Input
Output
Sample Input
4
2 3
3 2
1 1
4 5
Sample Output
2
2
0
3
题意
给你n个人,每个人有两个权值X,Y,所有的权值都是唯一的。
定义A比B强为 A x > B x A_x>B_x Ax>Bx或者 A y > B y A_y>B_y Ay>By,也就是可能A比B强的同时B比A强。
而且如果A比B强,B比C强,那么A比C强。
问每个人比多少个人强。
题解
考虑按照X这维从大到小,那么对于每个人来说,他比他后面的所有人强,所以他可以用后面最大的那个 y 1 y_1 y1去往前找小于这个 y 1 y_1 y1的最大 x 1 x_1 x1,再用这个 x 1 x_1 x1找后面最大的 y 2 y_2 y2,不断重复这个过程直到不能再往前找,之后我们用记忆划搜索的方法存储一个点往前找能找到的最小下标即可,这样保证每个点最多访问1次,但是在搜索的过程中需要注意,如果两次访问到一个点的 x x x去往后找 y y y,说明这个点已经不能找到更靠前的位置了,那么直接返回 d p [ i ] = i dp[i]=i dp[i]=i即可。
因为要O(1)的找到想找的位置,所以要预处理出两个数组
p r e [ i ] pre[i] pre[i]表示 1 − i 1-i 1−i中小于 y [ i ] y[i] y[i]的最小下标,需要用树状数组处理。
n e x [ i ] nex[i] nex[i]表示 1 − n 1-n 1−n中最大的 y [ i ] y[i] y[i]的下标,后缀max处理即可。
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<math.h>
using namespace std;
#define dbg(x) cout<<#x<<" = "<<x<<endl
#define dbg2(x,x2) cout<<#x<<" = "<<x<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x,x2,x3) cout<<#x<<" = "<<x<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int maxn =2e6+10;
const int INF = 0x3f3f3f3f;
struct dat
{
int x,y,id;
const bool operator < (const dat &b) const
{
return x>b.x;
}
}a[maxn];
int pre[maxn],nex[maxn],dp[maxn],ans[maxn];
int c[maxn];
int lowbit(int x) {return x&(-x);};
void add(int x,int val)
{
while(x<=2000000)
{
c[x]=min(c[x],val);
x+=lowbit(x);
}
}
int ask(int pos)
{
int ans=INF;
while(pos>0)
{
ans=min(ans,c[pos]);
pos-=lowbit(pos);
}
return ans;
}
bool vis[maxn];
int dfs(int pos,int flag)
{
if(dp[pos]!=INF) return dp[pos];
vis[pos]=true;
if(flag==0)
{
int mxpos=nex[pos];
dp[pos]=min(dp[pos],dfs(mxpos,1));
dp[pos]=min(dp[pos],pos);
vis[pos]=false;
return dp[pos];
}
else
{
int mxpos=pre[pos];
if(vis[mxpos]) dp[pos]=mxpos;
else dp[pos]=min(dp[pos],dfs(mxpos,0));
dp[pos]=min(dp[pos],pos);
vis[pos]=false;
return dp[pos];
}
}
int main()
{
freopen("codecoder.in","r",stdin);
freopen("codecoder.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
sort(a+1,a+1+n);
for(int i=0;i<=2000000;i++) c[i]=INF;
for(int i=1;i<=n;i++)
{
add(a[i].y,i);
pre[i]=ask(a[i].y);
}
int maxx=-1,pos=-1;
for(int i=n;i>=1;i--)
{
if(a[i].y>maxx) maxx=a[i].y,pos=i;
nex[i]=pos;
}
for(int i=1;i<=n;i++) dp[i]=INF;
for(int i=1;i<=n;i++)
{
if(dp[i]==INF)
{
vis[i]=true;
dfs(i,0);
vis[i]=false;
}
ans[a[i].id]=n-dp[i];
}
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}