正常人一般都写主席树,受到sxysxy神犇的启发,我也尝试了一下随机化算法,因为每一个区间内重复超过一半的数很容易随机出来,所以我们每次在区间内rand出一个位置,看该位置的数是否在区间内超过一半,如果rand次数超过固定值则输出 0 。
判断时可以使用stl,具体见代码。
期望复杂度 O(nlog^2n) 实际复杂度 玄学??
此代码在 WA TLE 和 AC 间徘徊….
bzoj 不让用 ctime 直接把time(0)换成其他的种子就行了
cnt大小随意
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 501000;
int ans,n,m,l,r,a[maxn];
vector<int> f[maxn];
int main()
{
srand(time(0));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) f[a[i]].push_back(i);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
bool ok=false;int cnt=20;
while(!ok&&--cnt)
{
ans=a[rand()%(r-l+1)+l];
int t1=upper_bound(f[ans].begin(),f[ans].end(),l-1)-f[ans].begin();
int t2=lower_bound(f[ans].begin(),f[ans].end(),r+1)-f[ans].begin();
if(t2-t1>(r-l+1)/2) ok=true;
}
if(!ok) puts("0");
else printf("%d\n",ans);
}
return 0;
}