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 59 8 7 8 9
1 2
3 4
4 4
1 4
2 4
Sample Output
98
8
16
16
HINT
1<=N<=10^51<=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;
}
相关文章推荐
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- Codeforces538F A Heap of Heaps【分块+差分求前缀和】
- 大矩阵的分块乘法及matlab实现
- Hadoop分块和分片
- bzoj-2741 L
- bzoj-3585 mex
- bzoj-2051 A Problem For Fun
- 算法马拉松8(差和问题)
- 1290 Counting Diff Pairs
- 【Violet 6】【BZOJ2724】蒲公英
- 【BZOJ4320】Homework
- 【BZOJ4216】Pig
- 【BZOJ2741】FOTILE模拟赛 L
- [2009国家集训队]小Z的袜子(hose) 分块做法
- NBUT 1457 分块
- codeforces #307 E. GukiZ and GukiZiana (分块)
- Codeforces Round #307 (Div. 2)E. GukiZ and GukiZiana(分块)
- 【分块】 CF 551 E GukiZ and GukiZiana
- Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana (分块)
- Codeforces Gym 100589A Queries on the Tree(树状数组+分块)