POJ 3419 Difference Is Beautiful

先处理出每一个i位置向左最远能到达的位置L[i]。每一次询问,要找到L,R区间中的p位置,p位置左边的L[i]都是小于L的,p位置开始,到R位置,L[i]都大于等于L,对于前者,最大值为p-L,后者求一个区间最大值即可。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
inline int read()
{
    char c = getchar();  while(!isdigit(c)) c = getchar();
    int x = 0;
    while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
    return x;
}

const int maxn=200000+10;
int n,a[maxn],b[maxn],c[maxn],q,L[maxn];
int dp[maxn][30],f[maxn];

void RMQ_init()
{
    for(int i=0;i<n;i++) dp[i][0]=f[i];
    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++)
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}

int RMQ(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;
    return max(dp[L][k],dp[R-(1<<k)+1][k]);
}

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=0;i<n;i++) scanf("%d",&a[i]),b[i]=a[i];
    sort(b, b + n); int sz = unique(b, b + n) - b;
    for(int i=0;i<n;i++) a[i]=lower_bound(b, b + sz, a[i])-b+1;
    memset(c,-1,sizeof c);
    for(int i=0;i<n;i++)
    {
        if(i==0) L[0]=0,c[a[i]]=0;
        else L[i]=max(L[i-1],c[a[i]]+1),c[a[i]]=i;
    }
    for(int i=0;i<n;i++) f[i]=i-L[i]+1;
    RMQ_init();
    for(int i=1;i<=q;i++)
    {
        int LL,RR; scanf("%d%d",&LL,&RR);
        int l=LL,r=RR,p=-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(L[mid]<LL) l=mid+1,p=mid;
            else r=mid-1;
        }
        int ans;
        if(p==-1) ans=RMQ(LL,RR);
        else if(p==RR) ans=RR-LL+1;
        else ans=max(p-LL+1,RMQ(p+1,RR));
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2016-08-05 12:00  Fighting_Heart  阅读(206)  评论(0编辑  收藏  举报