C++之路进阶——bzoj3524(Couriers)

本文提供了一种高效的算法解决序列中指定区间内重复元素超过区间长度一半的问题,通过构建数据结构来快速查找符合条件的元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

F.A.QsHomeDiscussProblemSetStatusRanklistContestModifyUser   gryz2016Logout捐赠本站
Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入、输出语句及数据类型及范围,避免无谓的RE出现。

3524: [Poi2014]Couriers

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1058  Solved: 363
[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行,每行两个数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

代码:

   

 1 #include<cstdio>
 2 #include<iostream>
 3  
 4 using namespace std;
 5  
 6 int n,m,sz;
 7 int root[500010],ls[10000010],rs[10000010],sum[10000010];
 8  
 9 void update(int l,int r,int x,int &y,int v)
10 {
11     y=++sz;
12     sum[y]=sum[x]+1;
13     if(l==r)return;
14     ls[y]=ls[x];
15     rs[y]=rs[x];
16     int mid=(l+r)>>1;
17     if(v<=mid) update(l,mid,ls[x],ls[y],v);
18     else update(mid+1,r,rs[x],rs[y],v);
19 }
20  
21 int que(int L,int R)
22  {
23     int l=1,r=n,mid,x,y,tmp=(R-L+1)>>1;
24     x=root[L-1];y=root[R];
25     while(l!=r)
26     {
27         if(sum[y]-sum[x]<=tmp)return 0;
28         mid=(l+r)>>1;
29         if(sum[ls[y]]-sum[ls[x]]>tmp)
30          {
31            r=mid;
32            x=ls[x];
33            y=ls[y];
34           } else
35         if(sum[rs[y]]-sum[rs[x]]>tmp)
36         {
37            l=mid+1;
38            x=rs[x];
39            y=rs[y];
40         }
41         else return 0;
42     }
43     return l;
44  }
45  
46 int main()
47 {
48     scanf("%d%d",&n,&m);
49     for(int i=1;i<=n;i++)
50     {
51         int x;
52         scanf("%d",&x);
53         update(1,n,root[i-1],root[i],x);
54     }
55     for(int i=1;i<=m;i++)
56     {
57         int l,r;
58         scanf("%d%d",&l,&r);
59         printf("%d\n",que(l,r));
60     }
61     return 0;
62 }

 

转载于:https://www.cnblogs.com/grhyxzc/p/5144184.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值