题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3524
可持久化线段树。连离散化都不用。找一个出现次数最大的数那就比较是左儿子大还是右儿子大找下去就可以了。
#include<cstring> #include<iostream> #include<algorithm> #include<cstdio> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 500500 #define ll long long using namespace std; int sum[maxn*20],ls[maxn*20],rs[maxn*20]; int root[maxn],a[maxn]; int ss,cnt,n,m,k,cnt2; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void add(int l,int r,int x,int &y,int val){ y=++cnt; sum[y]=sum[x]+1; if (l==r) return ; ls[y]=ls[x]; rs[y]=rs[x]; int mid=(l+r)/2; if (val<=mid) add(l,mid,ls[x],ls[y],val); else add(mid+1,r,rs[x],rs[y],val); } void jud(int x,int y){ int l=1,r=n; int a=root[y],b=root[x-1]; while (l<r){ int mid=(l+r)/2; if (sum[ls[a]]-sum[ls[b]]>sum[rs[a]]-sum[rs[b]]) {r=mid; a=ls[a]; b=ls[b];} else {l=mid+1; a=rs[a]; b=rs[b];} } if (sum[a]-sum[b]>(y-x+1)/2) printf("%d ",l); else puts("0"); } int main(){ n=read(); m=read(); rep(i,1,n) a[i]=read(); rep(i,1,n) add(1,n,root[i-1],root[i],a[i]); rep(i,1,m){ int x=read(),y=read(); jud(x,y); } return 0; }