您的位置:首页 > 其它

bzoj 4241: 历史研究

2016-07-02 18:53 351 查看

Description

IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。
日记中记录了连续N天发生的时间,大约每天发生一件。
事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。
JOI教授决定用如下的方法分析这些日记:
1.
选择日记中连续的一些天作为分析的时间段
2.
事件种类t的重要度为t*(这段时间内重要度为t的事件数)
3.
计算出所有事件种类的重要度,输出其中的最大值
现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。

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)

Source

JOI 2013~2014 春季training合宿 竞技1 By PoPoQQQ

我写的是离线的方法
把数列分块,然后把询问左端点属于同一块的放在一起,右端点增序
这样中间的块我们就可以直接暴力一个个点加进去了。
然后左边单独出来的几个单独统计
复杂度O(nsqrt(n))
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
long long sx[100001];
int belong[100001];
struct question
{
int l,r;
int p;
long long ans;
}ask[100001];
long long a[100001];
int id[100001],pos[100001];
long long ss[100001];
inline bool cmp1(question x,question y)
{
if(belong[x.l]<belong[y.l]||belong[x.l]==belong[y.l]&&x.r<y.r)
return true;
return false;
}
inline bool cmp2(question x,question y)
{
if(x.p<y.p)
return true;
return false;
}
inline bool cmp3(int x,int y)
{
if(a[x]<a[y])
return true;
return false;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
int i,j,k;
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
id[i]=i;
}
sort(id+1,id+1+n,cmp3);
int tot=0;
for(i=1;i<=n;i++)
{
if(a[id[i]]==a[id[i-1]])
pos[id[i]]=tot;
else
{
tot++;
pos[id[i]]=tot;
}
}
for(i=1;i<=q;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r);
ask[i].p=i;
}
int nt=sqrt(n);
for(i=1;i<=n;i++)
belong[i]=(i-1)/nt+1;
sort(ask+1,ask+1+q,cmp1);
int l=1,r=0;
for(i=1;i<=n;i+=nt)
{
int di=belong[i];
for(j=1;j<=tot;j++)
ss[j]=0;
r++;
l=r;
while(belong[ask[r].l]==di)
r++;
r--;
long long ans;
while(belong[ask[l].r]==di&&l<=r)
{
ans=0;
for(j=ask[l].l;j<=ask[l].r;j++)
{
ss[pos[j]]+=a[j];
if(ss[pos[j]]>ans)
ans=ss[pos[j]];
}
ask[l].ans=ans;
for(j=ask[l].l;j<=ask[l].r;j++)
ss[pos[j]]-=a[j];
l++;
}
int d=di*nt+1;
ans=0;
for(j=l;j<=r;j++)
{
for(k=d;k<=ask[j].r;k++)
{
ss[pos[k]]+=a[k];
if(ss[pos[k]]>ans)
ans=ss[pos[k]];
}
d=k;
long long tx=ans;
for(k=min(n,di*nt);k>=ask[j].l;k--)
{
ss[pos[k]]+=a[k];
if(ss[pos[k]]>tx)
tx=ss[pos[k]];
}
ask[j].ans=tx;
for(k=min(n,di*nt);k>=ask[j].l;k--)
ss[pos[k]]-=a[k];
}
}
sort(ask+1,ask+1+q,cmp2);
for(i=1;i<=q;i++)
printf("%lld\n",ask[i].ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分块