bzoj2223 [Coci 2009]PATULJCI

2223: [Coci 2009]PATULJCI

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1414  Solved: 612
[Submit][Status][Discuss]

Description

Input

 10 3 1 2 1 2 1 2 3 2 3 3 8 1 2 1 3 1 4 1 5 2 5 2 6 6 9 7 10

Output

no
yes 1
no
yes 1
no
yes 2
no
yes 3

HINT

Notice:输入第二个整数是序列中权值的范围Lim,即1<=ai(1<=i<=n)<=Lim。

1<=Lim<=10000

分析:

   其实这道题如果是第一次做还是有点难想出来的.它的突破口是什么呢?我们可以先查询权值在区间[L,R]内的数的出现次数是否大于(r - l + 1) / 2,是的话查询左半区间和右半区间是否分别大于.只要一个区间大于,就可以往那个子区间递归,这样不断地缩小区间大小,直到区间的L == R,就能确定那个数了.这就类似于二分找第k小的数的过程,每次判断小于当前数的数有多少个,最后不断缩小范围,或许这是求解已知排名的数是多少的通用解法吧.

 

   主席树的应用.

          插入操作就是普通的插入,查询操作采用步步逼近的方法,如果左区间的数的个数大于(r - l + 1) / 2,就在左区间中找,否则在右区间中找.最后直到l == r,返回l就可以了.

          应用主席树解题主要是要想到它的性质.是权值线段树,记录前缀等等.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxm = 500005;

int n,q,maxn,cnt,root[maxm];

struct node
{
    int left,right,sum;
}e[maxm * 20];

void update(int x,int &y,int l,int r,int v)
{
    e[y = ++cnt] = e[x];
    e[y].sum++;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    if (v <= mid)
        update(e[x].left,e[y].left,l,mid,v);
    else
        update(e[x].right,e[y].right,mid + 1,r,v);
}

int query(int l,int r,int x,int y,int k)
{
    if (l == r)
        return l;
    int mid = (l + r) >> 1;
    if (e[e[y].left].sum - e[e[x].left].sum > k)
        return query(l,mid,e[x].left,e[y].left,k);
    if (e[e[y].right].sum - e[e[x].right].sum > k)
        return query(mid + 1,r,e[x].right,e[y].right,k);
    return 0;
}

int main()
{
    scanf("%d%d",&n,&maxn);
    for (int i = 1; i <= n; i++)
    {
        int x;
        scanf("%d",&x);
        update(root[i - 1],root[i],1,maxn,x);
    }
    scanf("%d",&q);
    while (q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        int ans = query(1,maxn,root[l - 1],root[r],(r - l + 1) / 2);
        if (ans == 0)
            puts("no");
        else
            printf("yes %d\n",ans);
    }

    return 0;
}

 

posted @ 2018-02-09 15:35  zbtrs  阅读(176)  评论(0编辑  收藏  举报