1. 程式人生 > >【刷題】BZOJ 3524 [Poi2014]Couriers

【刷題】BZOJ 3524 [Poi2014]Couriers

last void -- 表示 一個數 amp con 出現 pos

Description

給一個長度為n的序列a。1≤a[i]≤n。
m組詢問,每次詢問一個區間[l,r],是否存在一個數在[l,r]中出現的次數大於(r-l+1)/2。如果存在,輸出這個數,否則輸出0。

Input

第一行兩個數n,m。
第二行n個數,a[i]。
接下來m行,每行兩個數l,r,表示詢問[l,r]這個區間。

Output

m行,每行對應一個答案。

Sample Input

7 5
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6

Sample Output

1
0
3
0
4

HINT

【數據範圍】
n,m≤500000

Solution

維護數字出現次數——主席樹
同樣用主席樹維護\(sum\)


每次查詢的時候選擇滿足條件的往下走就行了
因為一段數列中出現次數大於一半的至多只會有一個,所以這樣暴力做的復雜度是正確的

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define Mid ((l+r)>>1)
#define lson l,Mid
#define rson Mid+1,r
const int MAXN=500000+10;
int n,m,A[MAXN];
std::vector<int> V;
std::map<int,int> M;
struct ChairMan_Tree{
    int cnt,lc[MAXN<<5],rc[MAXN<<5],sum[MAXN<<5],root[MAXN];
    inline void init()
    {
        cnt=0;
        memset(lc,0,sizeof(lc));
        memset(rc,0,sizeof(rc));
        memset(sum,0,sizeof(sum));
    }
    inline void Build(int &rt,int l,int r)
    {
        rt=++cnt;
        sum[rt]=0;
        if(l==r)return ;
        Build(lc[rt],lson);
        Build(rc[rt],rson);
    }
    inline void Insert(int &rt,int l,int r,int last,int pos)
    {
        rt=++cnt;
        sum[rt]=sum[last]+1;
        lc[rt]=lc[last];
        rc[rt]=rc[last];
        if(l==r)return ;
        else
        {
            if(pos<=Mid)Insert(lc[rt],lson,lc[last],pos);
            else Insert(rc[rt],rson,rc[last],pos);
        }
    }
    inline int Query(int now,int last,int l,int r,int k)
    {
        if(sum[now]-sum[last]<=k)return 0;
        if(l==r)return l;
        else
        {
            if(sum[lc[now]]-sum[lc[last]]>k)return Query(lc[now],lc[last],lson,k);
            else return Query(rc[now],rc[last],rson,k);
        }
    }
};
ChairMan_Tree T;
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void discre()
{
    sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    for(register int i=1;i<=n;++i)
    {
        int pre=A[i];
        A[i]=lower_bound(V.begin(),V.end(),A[i])-V.begin()+1;
        M[A[i]]=pre;
    }
}
int main()
{
    read(n);read(m);
    for(register int i=1;i<=n;++i)
    {
        read(A[i]);
        V.push_back(A[i]);
    }
    discre();
    T.init();
    T.Build(T.root[0],1,n);
    for(register int i=1;i<=n;++i)T.Insert(T.root[i],1,n,T.root[i-1],A[i]);
    while(m--)
    {
        int l,r;
        read(l);read(r);
        write(T.Query(T.root[r],T.root[l-1],1,n,(r-l+1)/2),'\n');
    }
    return 0;
}

【刷題】BZOJ 3524 [Poi2014]Couriers