3524: [Poi2014]Couriers -- 主席树

3524: [Poi2014]Couriers

Time Limit: 20 Sec  Memory Limit: 256 MB

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<cstdio>
#define N 10000010
#define M 500010
inline 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,sz,rt[M],ls[N],rs[N],sum[N];
inline void add(int l,int r,int a,int &p,int v)
{
    p=++sz;sum[p]=sum[a]+1;
    if(l==r)return;
    ls[p]=ls[a];rs[p]=rs[a];
    int mid=(l+r)>>1;
    if(v<=mid) add(l,mid,ls[a],ls[p],v);
    else add(mid+1,r,rs[a],rs[p],v);
}
inline int qwq(int L,int R)
{
    int x=rt[L-1],y=rt[R],md=(R-L+1)>>1,l=1,r=n,mid;
    while(l<r)
    {
        if(sum[y]-sum[x]<=md) return 0;
        mid=(l+r)>>1;
        if(sum[ls[y]]-sum[ls[x]]>md){r=mid;x=ls[x];y=ls[y];}
        else if(sum[rs[y]]-sum[rs[x]]>md){l=mid+1;x=rs[x];y=rs[y];}
        else return 0;
    }
    return l;
}
int x,l,r;
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        x=read();
        add(1,n,rt[i-1],rt[i],x);
    }
    while(m--)
    {
        l=read();r=read();
        printf("%d\n",qwq(l,r));
    }
}
时间: 2024-08-23 19:27:39

3524: [Poi2014]Couriers -- 主席树的相关文章

BZOJ 3524: [Poi2014]Couriers( 主席树 )

卡我空间.... 这道题应该是主席树入门题...无修改 , 离散化都不用...出题人业界良心啊 一开始的空白树我 build 出来结果就多了整整 2n 个 Node , 然后就 MLE 了... ( 双倍经验 , 另一道见上图 ) ---------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring&g

[BZOJ2223][BZOJ3524][Poi2014]Couriers 主席树

3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 2436  Solved: 960[Submit][Status][Discuss] Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. Input 第一行两个数n,m.第二行n个数,a[i].接下来m行,

bzoj 3524 [POI2014]KUR-Couriers (主席树)

题目大意:给你一个序列,求某个区间出现次数大于一半的数是什么 主席树裸题,刷刷水题提升自信= = 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define ll long long 5 #define il inline 6 #define N 500100 7 using namespace std; 8 //re 9 int n,m,tot; 10 int a[N],root[

BZOJ 3524: [Poi2014]Couriers

3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1905  Solved: 691[Submit][Status][Discuss] Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. Input 第一行两个数n,m.第二行n个数,a[i].接下来m行,

BZOJ 3524 POI 2014 Couriers 主席树

题目大意 给出一个序列,问一段区间内有没有出现过一半以上的数字. 思路 用主席树取区间出来,在权值线段树上找. CODE #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 500010 #define MAXR 10000010 using namespace std

[bzoj3524][Poi2014]Couriers_主席树

Couriers bzoj-3524 Poi-2014 题目大意:给定n个数的序列,询问区间内是否存在一个在区间内至少出现了(区间长度>>1)次的数.如果有,输出该数,反之输出0. 注释:$1\le n,m\le 5\cdot 10^5$. 想法:主席树裸题. 主流做法就是弄一个Existence数组询问有没有这样的数,然后查询区间中位数即可. 但是可以在query的时候强行查询,因为没有输出0,直接输出即可. 最后,附上丑陋的代码... ... #include <iostream&g

BZOJ 3524 [Poi2014]Couriers(二分+蒙特卡罗)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3524 [题目大意] 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2. 如果存在,输出这个数,否则输出0. [题解] 我们可以在[l,r]中随机一个位置检验这个位置上数是不是答案, 检测方法可以在数组中保存每个数在序列中的不同位置,二分即可 选中答案的概率为1/2,我们做k次蒙特卡罗,正确率

BZOJ_3524_[Poi2014]Couriers_主席树

题意:给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. 分析: 区间众数我们可以用主席树搞定 具体地,比较左右子树siz大小即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 500050 int t

P3567 [POI2014]KUR-Couriers 主席树

这个题比一般主席树还要简单,但是用来练习主席树再好不过了,在这里我再放一下主席树板子. 代码: #include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) fo