#include<iostream> #include<algorithm> #include<map> #include<vector> #include<cstdio> #include<ctime> #include<cstring> #include<cstdlib> #define ll long long #define inf 0x3f3f3f3f #define N 1000009 using namespace std; map<int,int>mp;//离散化 vector<int> vec[N];//记录每个值出现的位置 int blo[N],v[N],val[N],cnt[N]; int f[505][505];//记录(i,j)的众数 int id,len,n; ll read() { char ch=getchar();ll f=1,ret=0; while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return f*ret; } void pre(int x)//预处理从x~i(i=x~n)的众数 { int mx=0,cur=0; memset(cnt,0,sizeof(cnt)); for (int i=(x-1)*len+1;i<=n;i++) { int pos=blo[i]; cnt[v[i]]++; if (cnt[v[i]]>mx||(cnt[v[i]]==mx&&val[v[i]]<val[cur]))//如果v[i]出现的次数多,或者次数一样多但值小 cur=v[i],mx=cnt[v[i]]; f[x][pos]=cur;//在(x,blo[i])的块间众数更新 } } int ask(int l,int r,int x)//询问在区间(l,r)之间,数值为x的数出现的次数 {return (upper_bound(vec[x].begin(),vec[x].end(),r)-lower_bound(vec[x].begin(),vec[x].end(),l));} int query(int l,int r) { int p=blo[l],q=blo[r],ans=f[p+1][q-1],mx=0; mx=ask(l,r,ans);//先找在块(blo[l]+1,blo[r]-1)的众数在区间(l,r)之间出现的次数 for (int i=l;i<=min(p*len,r);i++)//然后我们暴力处理从整块两边多余的部分 { int t=ask(l,r,v[i]); if (t>mx||(t==mx&&val[ans]>val[v[i]])) mx=t,ans=v[i]; } if (p!=q) for (int i=(q-1)*len+1;i<=r;i++) { int t=ask(l,r,v[i]); if (t>mx||(t==mx&&val[ans]>val[v[i]])) mx=t,ans=v[i]; } return val[ans]; } int main() { n=read();len=200; for (int i=1;i<=n;i++) { v[i]=read(); if (!mp[v[i]])//如果这个值并没有离散化,离散化 { mp[v[i]]=++id; val[id]=v[i]; } v[i]=mp[v[i]]; vec[v[i]].push_back(i); } for (int i=1;i<=n;i++) blo[i]=(i-1)/len+1; for (int i=1;i<=blo[n];i++) pre(i); for (int i=1;i<=n;i++) { int l=read(),r=read(); if (l>r) swap(l,r); printf("%d\n",query(l,r)); } return 0; }
【loj6285】 数列分块入门 9
猜你喜欢
转载自blog.csdn.net/dadatu_zhao/article/details/80559189
今日推荐
周排行