Description
IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。
日记中记录了连续N天发生的时间,大约每天发生一件。
事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。
JOI教授决定用如下的方法分析这些日记:
- 选择日记中连续的一些天作为分析的时间段
- 事件种类t的重要度为t*(这段时间内重要度为t的事件数)
- 计算出所有事件种类的重要度,输出其中的最大值 现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。
Input
第一行两个空格分隔的整数N和Q,表示日记一共记录了N天,询问有Q次。
接下来一行N个空格分隔的整数X1…XN,Xi表示第i天发生的事件的种类
接下来Q行,第i行(1<=i<=Q)有两个空格分隔整数Ai和Bi,表示第i次询问的区间为[Ai,Bi]
。
Output
输出Q行,第i行(1<=i<=Q)一个整数,表示第i次询问的最大重要度
Sample Input
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
Sample Output
9
8
8
16
16
HINT
1<=N<=10^5
1<=Q<=10^5
1<=Xi<=10^9 (1<=i<=N)
题解
分块…
预处理块与块之间答案
然后就没了…
为什么我的常数这么大啊
为什么我还要调整块的大小啊…
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
inline LL _max(LL x,LL y){return x>y?x:y;}
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void write(LL x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
inline void print(LL x){write(x);puts("");}
struct LSnode{int y,p;}w[100005];
bool cmp(LSnode n1,LSnode n2){return n1.y<n2.y;}
int cal[110000],LS[110000],fac[110000],n,m,ln;
int pos[110000],block,st[630],ed[630];
LL pr[630][630];int sum[110000];
int gg[110000],tim;
int S[630][110000];
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n=read();m=read();ln=n;
for(int i=1;i<=n;i++)w[i].y=read(),w[i].p=i;
sort(w+1,w+1+n,cmp);
int tt=0;
for(register int i=1;i<=n;i++)
{
if(w[i].y!=w[i-1].y)tt++;
cal[w[i].p]=tt;fac[tt]=w[i].y;
}
block=pow(n,0.444);
for(register int i=1;i<=n;i++)
{
pos[i]=(i-1)/block+1;
if(pos[i]!=pos[i-1])ed[pos[i-1]]=i-1,st[pos[i]]=i;
}
ed[pos[n]]=n;st[pos[1]]=1;block=pos[n];
for(register int i=1;i<=block;i++)
{
for(register int j=1;j<=ln;j++)S[i][j]=S[i-1][j];
for(register int j=st[i];j<=ed[i];j++)S[i][cal[j]]++;
}
for(register int i=1;i<=block;i++)
{
LL ans=0;tim++;
for(register int j=i;j<=block;j++)
{
for(register int k=st[j];k<=ed[j];k++)
{
if(gg[cal[k]]!=tim)gg[cal[k]]=tim,sum[cal[k]]=0;
sum[cal[k]]++,ans=_max(ans,(LL)sum[cal[k]]*fac[cal[k]]);
}
pr[i][j]=ans;
}
}
memset(sum,0,sizeof(sum));
while(m--)
{
int l=read(),r=read();
int u=pos[l]+1,v=pos[r]-1;tim++;
if(u>v)
{
LL ans=0;
for(register int i=l;i<=r;i++)
{
if(gg[cal[i]]!=tim)gg[cal[i]]=tim,sum[cal[i]]=0;
sum[cal[i]]++;ans=_max(ans,(LL)sum[cal[i]]*fac[cal[i]]);
}
print(ans);
}
else
{
LL ans=pr[u][v];
for(register int i=st[v+1];i<=r;i++)
{
if(gg[cal[i]]!=tim)gg[cal[i]]=tim,sum[cal[i]]=S[v][cal[i]]-S[u-1][cal[i]];
sum[cal[i]]++;ans=_max(ans,(LL)sum[cal[i]]*fac[cal[i]]);
}
for(register int i=l;i<=ed[u-1];i++)
{
if(gg[cal[i]]!=tim)gg[cal[i]]=tim,sum[cal[i]]=S[v][cal[i]]-S[u-1][cal[i]];
sum[cal[i]]++;ans=_max(ans,(LL)sum[cal[i]]*fac[cal[i]]);
}
print(ans);
}
}
return 0;
}