BZOJ3524[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

Source

By Dzy


solution:主席树+二分

主席树模版题,由于题目规定a[i]<=n,所以不用离散化。建好树以后二分出答案。

ps:区间中个数大于(r-l+1)/2的数最多有一个

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 500005
struct Node{
    int ls, rs, sum;
}t[N*20];
int rt[N], a[N], cnt, n;
void insert( int l, int r, int pre, int &nd, int val ){
    nd=++cnt;
    t[nd]=t[pre];
    t[nd].sum++;
    if( l==r ) return;
    int mid=(l+r)>>1;
    if( val<=mid ) insert( l, mid, t[pre].ls, t[nd].ls, val);
    else insert( mid+1, r, t[pre].rs, t[nd].rs, val);
}
void query( int x, int y ){
    int l=1, r=n;
    int pre=rt[x-1], nd=rt[y];
    while( l<r ){
        int mid=(l+r)>>1;
        if( t[t[nd].ls].sum-t[t[pre].ls].sum>t[t[nd].rs].sum-t[t[pre].rs].sum) r=mid, pre=t[pre].ls, nd=t[nd].ls;
        else l=mid+1, pre=t[pre].rs, nd=t[nd].rs;
    }
    if( t[nd].sum-t[pre].sum>((y-x+1)>>1) ) printf("%d\n", l);
    else puts("0");
}
int main(){
    int m;
    scanf( "%d%d", &n, &m );
    cnt=0;
    for ( int i=1; i<=n; i++ ) scanf("%d",&a[i]);
    for ( int i=1; i<=n; i++ ) insert(1,n,rt[i-1],rt[i],a[i]);
    while( m-- ){
        int x, y;
        scanf("%d%d",&x,&y);
        query(x,y);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值