HDU2836 Traversal

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU2836 Traversal相关的知识,希望对你有一定的参考价值。

题解:

dp+树状数组优化

跟hdu2227差不多,只不过改变了一下范围。更改一下sum的方式即可

但是这题的a[i]范围比较大。

在用树状数组时,一种是直接使用map,另一种是使用hash+二分

代码:

map优化 1060ms

#include<bits/stdc++.h>
using namespace std;
#define LL long long 
const int N=100010;
const int M=100000100;
const int mod=9901;

int n,h,Min,Max;
int a[N],dp[N];
map<int,int> c;

int lowbit(int x){return x&-x;}

void add(int x,int v){
    while(x<M){
        c[x]+=v;
        c[x]%=mod;
        x+=lowbit(x);
    }
}

int sum(int x){
    int cnt=0;
    while(x){
        cnt+=c[x];
        cnt%=mod;
        x-=lowbit(x);
    }
    return cnt;
}

int main(){
    while(~scanf("%d%d",&n,&h)){
        c.clear();
        for(int i=1;i<=n;i++){
             scanf("%d",&a[i]);
             Min=max(a[i]-h,1);
             Max=min(a[i]+h,M-5);
             dp[i]=sum(Max)-sum(Min-1);
             add(a[i],dp[i]+1);
        }
        printf("%d\n",((sum(M)-n)%mod+mod)%mod);
    }
    return 0;
}

 

hash+二分 156ms

#include<bits/stdc++.h>
using namespace std;
#define LL long long 
const int N=100010;
const int M=100000100;
const int mod=9901;

int a[N],t[N],c[N];
int n,h,tot;

int lowbit(int x){return x&-x;}

void add(int x,int v){
    while(x<=tot){
        c[x]+=v;
        c[x]%=mod;
        x+=lowbit(x);
    }
}

int sum(int x){
    int cnt=0;
    while(x){
        cnt+=c[x];
        cnt%=mod;
        x-=lowbit(x);
    }
    return cnt;
}

int Bin(int v){
    int l=1,r=tot;
    while(l<=r){
        int m=(l+r)>>1;
        if(v==t[m]) return m;
        if(v>t[m]) l=m+1;
        else       r=m-1;
    }
}

int lBin(int v){
    int l=1,r=tot,ans=1;
    while(l<=r){
        int m=(l+r)>>1;
        if(t[m]>=v){
            r=m-1;
            ans=m;
        }
        else l=m+1;
    }
    return ans;
}

int rBin(int v){
    int l=1,r=tot,ans=tot;
    while(l<=r){
        int m=(l+r)>>1;
        if(t[m]<=v){
            l=m+1;
            ans=m;
        }
        else r=m-1;
    }
    return ans;
}

int main(){
    while(~scanf("%d%d",&n,&h)){
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            t[i]=a[i];
        }
        sort(t+1,t+n+1);
        tot=0;
        for(int i=1;i<=n;i++){
            if(i==1||t[i]!=t[i-1]){
                t[++tot]=t[i];//去掉重复元素 
                c[tot]=0;
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            int nidx=Bin(a[i]);
            int l=lBin(a[i]-h);//大于等于a[i]-h的最小值位置 
            int r=rBin(a[i]+h);//小于等于a[i]+h的最大值位置 
            int val=(sum(r)-sum(l-1)+mod)%mod;
            ans=(ans+val+1)%mod;
            add(nidx,val+1);
        }
        printf("%d\n",((ans-n)%mod+mod)%mod);
    }
    return 0;
}

 

以上是关于HDU2836 Traversal的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2836: 魔法树

BZOJ 2836 魔法树

ZOJ2836-Number Puzzle-容斥原理

bzoj2836魔法树 树链剖分+线段树

RP2836 OUT0-OUT7 对应关系

rp2836 网卡以及串口与接插件位置关系