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次蒙特卡罗,正确率就为1-(1/2)^k,
  复杂度为O(kmlogn)。

  主席树做法见 LINK

 

【代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int N=500010;
vector<int> pos[N];
int a[N],l,r,n,m;
int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++)pos[i].clear();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);  
            pos[a[i]].push_back(i);
        }
        while(m--){
            scanf("%d%d",&l,&r);
            int len=r-l+1,find=0;
            for(int k=1;k<=20;k++){
                int u=a[l+rand()%len];
                int st=lower_bound(pos[u].begin(),pos[u].end(),l)-pos[u].begin();
                int en=upper_bound(pos[u].begin(),pos[u].end(),r)-pos[u].begin();
                if((en-st)*2>len){find=u;break;}
            }if(find)printf("%d\n",find);
            else puts("0");
        }
    }return 0;
}
posted @   forever97  阅读(144)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示