【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强为 A x > B x A_x>B_x 或者 A y > B y A_y>B_y ,也就是可能A比B强的同时B比A强。

而且如果A比B强,B比C强,那么A比C强。

问每个人比多少个人强。

题解

考虑按照X这维从大到小,那么对于每个人来说,他比他后面的所有人强,所以他可以用后面最大的那个 y 1 y_1 去往前找小于这个 y 1 y_1 的最大 x 1 x_1 ,再用这个 x 1 x_1 找后面最大的 y 2 y_2 ,不断重复这个过程直到不能再往前找,之后我们用记忆划搜索的方法存储一个点往前找能找到的最小下标即可,这样保证每个点最多访问1次,但是在搜索的过程中需要注意,如果两次访问到一个点的 x x 去往后找 y y ,说明这个点已经不能找到更靠前的位置了,那么直接返回 d p [ i ] = i dp[i]=i 即可。

因为要O(1)的找到想找的位置,所以要预处理出两个数组

p r e [ i ] pre[i] 表示 1 i 1-i 中小于 y [ i ] y[i] 的最小下标,需要用树状数组处理。

n e x [ i ] nex[i] 表示 1 n 1-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;
}
发布了299 篇原创文章 · 获赞 117 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/101536318
今日推荐