ZOJ 3633 Alice's present 线段树+RMQ

题意: 给出一个序列和 M 个询问,对于每个询问输出询问区间内从右向左第一个出现次数超过 2 的数。

分析:预处理用 before[i] 表示第 i 个数之前出现的距离第 i 个数最近求和 第 i  数相等的数的值。

        区间查询的时候先查询右儿子区间,再查询能合并的区间,再查询左儿子区间。

#include<stdio.h>
#include<string.h>
#include<map>
using namespace std;
#define maxn 500005
#define max(a,b)(a)>(b)?(a):(b)
int va[maxn];
int before[maxn];
int maxr[maxn<<3];
void creat(int l,int r,int rt)
{
    if(l==r)
    {
        maxr[rt]=before[l];
        return;
    }
    int mid=(l+r)>>1;
    creat(l,mid,rt<<1);
    creat(mid+1,r,rt<<1|1);
    maxr[rt]=max(maxr[rt<<1],maxr[rt<<1|1]);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
        return maxr[rt];
    if(l==r)
        return 0;
    int t1=0,t2=0;
    int mid=(l+r)>>1;
    if(R>mid)
        t1=query(L,R,mid+1,r,rt<<1|1);
    if(L<=mid)
        t2=query(L,R,l,mid,rt<<1);
    if(t1!=0&&t1>=L)
    {
        if(t2>=L)
            return max(t1,t2);
        return t1;
    }
    if(t2>=L)
        return t2;
    return 0;

}
int main()
{
    int i,n,p,m,a,b,res;
    while(scanf("%d",&n)!=EOF)
    {
        map<int,int>v;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&va[i]);
            before[i]=v[va[i]];
            v[va[i]]=i;
        }
        creat(1,n,1);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            res=query(a,b,1,n,1);
            if(res)
                printf("%d\n",va[res]);
            else printf("OK\n");
        }
        printf("\n");
    }
    return 0;
}

 

 rmq:

View Code
#include <stdio.h>
#include <cstring>
#include <map>
#include <cmath>
#include <iostream>
int max(int a,int b)
{  return a>b?a:b; }
using namespace std;
#define clr(x) memset(x, 0, sizeof(x))
const int M = 500010;
int dp[M][18];
void makermq(int n,int b[])
{
    int i,j;
    for(i=1;i<=n;i++)
        dp[i][0]=b[i];
    for(j=1;(1<<j)<=n;j++)
        for(i=1;i+(1<<j)-1<=n;i++)
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int s,int v)
{
    int k=(int)(log((v-s+1)*1.0)/log(2.0));
    return max(dp[s][k],dp[v-(1<<k)+1][k]);
}
int arr[500010];
int af[500010];
int main()
{
    int i, j, k;
    int n, m;
    string num;
    int a, b, tmp;
    while(cin >> n)
    {
        map<int, int> mm;
        clr(dp);
        clr(arr);
        for(i = 1; i <= n; ++i)
        {
            cin >> af[i];
            arr[i] = mm[af[i]];
            mm[af[i]] = i;
        }
        makermq(n, arr);
        cin >> m;
        while(m--)
        {
            cin >> a >> b;
            tmp = rmq(a, b);
            if(tmp == 0 || tmp < a || tmp > b) puts("OK\n");
            else printf("%d\n", af[tmp]);
        }
    }
    return 0;
}

 

posted @ 2012-08-26 19:40  'wind  阅读(277)  评论(2编辑  收藏  举报