【2016-2017NEERC- gym101142-C.CodeCoder vs TopForces】樹狀數組+記憶化搜索

CodeCoder vs TopForces

題目鏈接:

https://codeforc.es/gym/101142

Description

在這裏插入圖片描述

Input

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fBZIuEQW-1569568090672)(C:\Users\biubiubiu\AppData\Roaming\Typora\typora-user-images\1569566816839.png)]

Output

在這裏插入圖片描述

Sample Input

4
2 3
3 2
1 1
4 5

Sample Output

2
2
0
3

題意

給你n個人,每個人有兩個權值X,Y,所有的權值都是唯一的。

定義A比B強爲Ax>BxA_x>B_x或者Ay>ByA_y>B_y,也就是可能A比B強的同時B比A強。

而且如果A比B強,B比C強,那麼A比C強。

問每個人比多少個人強。

題解

考慮按照X這維從大到小,那麼對於每個人來說,他比他後面的所有人強,所以他可以用後面最大的那個y1y_1去往前找小於這個y1y_1的最大x1x_1,再用這個x1x_1找後面最大的y2y_2,不斷重複這個過程直到不能再往前找,之後我們用記憶劃搜索的方法存儲一個點往前找能找到的最小下標即可,這樣保證每個點最多訪問1次,但是在搜索的過程中需要注意,如果兩次訪問到一個點的xx去往後找yy,說明這個點已經不能找到更靠前的位置了,那麼直接返回dp[i]=idp[i]=i即可。

因爲要O(1)的找到想找的位置,所以要預處理出兩個數組

pre[i]pre[i]表示1i1-i中小於y[i]y[i]的最小下標,需要用樹狀數組處理。

nex[i]nex[i]表示1n1-n中最大的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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章