【BZOJ3524/2223/POI2014】KUR-Couriers

10 篇文章 0 订阅

                        「BZOJ3524 / 2223」[POI2014] Couriers

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

 

解析:

       主席树板题。

 

代码:

#include <bits/stdc++.h>
using namespace std;

const int Max=500005;
int n,m,tot;
int tree[Max*20],root[Max*20],lc[Max*20],rc[Max*20];

inline int get_int()
{
    int x=0,f=1;
    char c;
    for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
    if(c=='-') f=-1,c=getchar();
    for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}
inline void print(int x)
{
    if(x>9) print(x/10);
    putchar('0'+x%10);
}

inline void add(int fa,int &now,int l,int r,int x)
{
    now=++tot,tree[now]=tree[fa]+1,lc[now]=lc[fa],rc[now]=rc[fa];
    if(l==r) return;
    int mid=(l+r)>>1;
    if(x<=mid) add(lc[fa],lc[now],l,mid,x);
    else add(rc[fa],rc[now],mid+1,r,x);
}
inline int Q(int root1,int root2,int l,int r,int x)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(tree[lc[root1]]-tree[lc[root2]]>x) return Q(lc[root1],lc[root2],l,mid,x);
    else if(tree[rc[root1]]-tree[rc[root2]]>x) return Q(rc[root1],rc[root2],mid+1,r,x);
    else return 0;
}

int main()
{
    n=get_int(),m=get_int();
    for(int i=1;i<=n;i++)
    {
      int x=get_int();
      add(root[i-1],root[i],0,n,x);
    }
    while(m--)
    {
      int l=get_int(),r=get_int();
      print(Q(root[r],root[l-1],0,n,(r-l+1)/2)),putchar('\n');
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值