您的位置:首页 > 其它

BZOJ 4241 历史研究

2017-03-07 10:52 417 查看
就是区间众数的做法啦。。一模一样。

分块这种东西真的很容易写错。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 100050
using namespace std;
int n,q,x[maxn],hash[maxn],cnt=0,s[maxn],top=0,blo[maxn],tot=0,se[maxn],l,r;
int num[2050][2050],len,ll[maxn];
vector <int> v[maxn];
int read()
{
int data=0;char ch;
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9')
{
data=data*10+ch-'0';
ch=getchar();
}
return data;
}
void build()
{
for (int i=1;i<=n;i++) hash[++cnt]=x[i];
sort(hash+1,hash+cnt+1);cnt=unique(hash+1,hash+cnt+1)-hash-1;
len=80;tot=1;
for (int i=1;i<=n;i++)
{
x[i]=lower_bound(hash+1,hash+cnt+1,x[i])-hash;
v[x[i]].push_back(i);
blo[i]=tot;
if ((i%len==0) || (i==n))
{
se[tot]=i;
tot++;
}
}
tot--;
for (int i=1;i<=tot;i++)
{
long long mx=0;int ret;
memset(ll,0,sizeof(ll));
for (int j=se[i-1]+1;j<=n;j++)
{
ll[x[j]]++;
if (mx<(long long)ll[x[j]]*hash[x[j]]) {mx=(long long)ll[x[j]]*hash[x[j]];ret=x[j];}
if ((j%len==0) || (j==n)) num[i][blo[j]]=ret;
}
}
}
int ask(int x,int num)
{
int l=0,r=v[num].size()-1,ans=-1,mid;
while (l<=r)
{
mid=(l+r)>>1;
if (v[num][mid]<=x) {ans=mid;l=mid+1;}
else r=mid-1;
}
return ans+1;
}
long long work(int l,int r)
{
top=0;
if (blo[l]+1>=blo[r])
{
for (int i=l;i<=r;i++)
s[++top]=x[i];
}
else
{
s[++top]=num[blo[l]+1][blo[r]-1];
for (int i=l;i<=se[blo[l]];i++) s[++top]=x[i];
for (int i=se[blo[r]-1]+1;i<=r;i++) s[++top]=x[i];
}
long long ret=0;
for (int i=1;i<=top;i++)
ret=max(ret,(long long)(ask(r,s[i])-ask(l-1,s[i]))*hash[s[i]]);
return ret;
}
int main()
{
n=read();q=read();
for (int i=1;i<=n;i++) x[i]=read();
build();
for (int i=1;i<=q;i++)
{
l=read();r=read();
printf("%lld\n",work(l,r));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: