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比B強的同時B比A強。
而且如果A比B強,B比C強,那麼A比C強。
問每個人比多少個人強。
題解
考慮按照X這維從大到小,那麼對於每個人來說,他比他後面的所有人強,所以他可以用後面最大的那個去往前找小於這個的最大,再用這個找後面最大的,不斷重複這個過程直到不能再往前找,之後我們用記憶劃搜索的方法存儲一個點往前找能找到的最小下標即可,這樣保證每個點最多訪問1次,但是在搜索的過程中需要注意,如果兩次訪問到一個點的去往後找,說明這個點已經不能找到更靠前的位置了,那麼直接返回即可。
因爲要O(1)的找到想找的位置,所以要預處理出兩個數組
表示中小於的最小下標,需要用樹狀數組處理。
表示中最大的的下標,後綴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;
}