【BZOJ-2223】PATULJCI 可持久化线段树

2223: [Coci 2009]PATULJCI

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 728  Solved: 292
[Submit][Status][Discuss]

Description

Input

Output

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

Sample Input

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

Sample Output

HINT

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

1<=Lim<=10000

Source

 

Solution

题面应该是出问题了

方法很简单,主席树的建法,不过询问的是次数,裸题

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int n,m,lim;
#define maxn 500001
int sum[maxn*20],ll[maxn*20],rr[maxn*20],root[maxn<<2],sz; 
void insert(int l,int r,int &now,int fat,int val) 
{ 
    now=++sz; sum[now]=sum[fat]+1; 
    if (l==r) return; 
    ll[now]=ll[fat],rr[now]=rr[fat]; 
    int mid=(l+r)>>1; 
    if (val<=mid) insert(l,mid,ll[now],ll[fat],val); 
    else insert(mid+1,r,rr[now],rr[fat],val); 
} 
int query(int l,int r,int L,int R) 
{ 
    int LL=root[L-1],RR=root[R];
    while (l!=r)
        {
            int mid=(l+r)>>1;
            if (sum[RR]-sum[LL]<=(R-L+1)/2) return 0;
            if (sum[ll[RR]]-sum[ll[LL]]>(R-L+1)/2)
                LL= ll[LL],RR=ll[RR],r=mid;
            else if (sum[rr[RR]]-sum[rr[LL]]>(R-L+1)/2)
                    LL=rr[LL],RR=rr[RR],l=mid+1; 
                  else return 0; 
        }
    return l;
}

int main()
{
    n=read();lim=read();
    for (int a,i=1; i<=n; i++)
        a=read(),insert(1,lim,root[i],root[i-1],a);
    m=read();
    for (int l,r,i=1; i<=m; i++)    
        {
            l=read(),r=read(); if (l>r) swap(l,r);
            int ans=query(1,lim,l,r);
            if (!ans) puts("no");
            else printf("yes %d\n",ans);
        }
    return 0;
} 

心态爆炸了,做做水题

 

posted @ 2016-04-02 18:51  DaD3zZ  阅读(346)  评论(0编辑  收藏  举报