Description
Professor JOI, the first person to study the history of IOI, recently obtained a diary written by the residents of ancient IOI. In order to study the life of ancient IOI through this diary, Professor JOI began to investigate the events recorded in the diary.
The diary records the time of N consecutive days, about one occurrence per day.
There are different kinds of events. The type of event on day i (1 < = i < = n) is represented by an integer Xi. The larger Xi is, the larger the event size is.
Professor JOI decided to analyze these diaries in the following ways:
1. Select consecutive days in the journal as the time period for analysis
2. The importance of event type T is t * (the number of events with importance of T in this period)
3. Calculate the importance of all event types and output the maximum value
Now you are asked to make a program to help teach analysis. Each time you give an analysis range, you need to output the maximum value of importance.
1<=N<=10^5
1<=Q<=10^5
1<=Xi<=10^9 (1<=i<=N)
Solution
Roll back team Mo, get to a new position
For some information that can be easily inserted but not deleted, you can consider rolling back Mo team
At the beginning, I wrote "Mo team + line tree". I found that one wave of complexity can't pass without gg
For the query interval (l,r), we set the starting point tl to the right endpoint of the block where l is, and tr to l-1
Move the right pointer tr continuously to the right, and note that the answer is tmp1 at this time
Keep moving the left pointer tl to the left, and the answer is to ask for the answer
Roll back the left pointer tl to the starting point (the right endpoint of the block where l is) and restore the current answer to tmp1
If the l of the current query is the same as that of the last query, the left and right pointers will be reserved, otherwise the starting point will be readjusted
Note that we have a very special way of sorting queries, which can avoid deletion and maintain excellent complexity
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
typedef long long LL;
const int N=100005;
struct Q {int l,r,id;} q[N];
int a[N],b[N],bel[N],B;
LL ans[N],vec[N],rec[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
bool cmp(Q a,Q b) {
return bel[a.l]<bel[b.l]||bel[a.l]==bel[b.l]&&(a.r<b.r);
}
int main(void) {
int n=read(),m=read(); B=sqrt(n);
rep(i,1,n) {
a[i]=read();
b[i]=a[i]; bel[i]=(i-1)/B+1;
}
std:: sort(b+1,b+n+1);
int size=std:: unique(b+1,b+n+1)-b-1;
rep(i,1,n) a[i]=std:: lower_bound(b+1,b+size+1,a[i])-b;
rep(i,1,m) q[i]=(Q) {read(),read(),i};
std:: sort(q+1,q+m+1,cmp);
int l=1,r=0;
LL tmp1=0,tmp2=0,pos;
rep(i,1,m) {
if (bel[q[i].l]!=bel[q[i-1].l]) {
fill(rec,0);
pos=l=bel[q[i].l]*B+1,r=l-1;
tmp1=tmp2=0;
}
if (bel[q[i].l]==bel[q[i].r]) {
rep(j,q[i].l,q[i].r) {
vec[a[j]]+=b[a[j]];
ans[q[i].id]=std:: max(ans[q[i].id],vec[a[j]]);
}
rep(j,q[i].l,q[i].r) vec[a[j]]-=b[a[j]];
continue;
}
for (;r<q[i].r;) { r++;
rec[a[r]]+=b[a[r]];
tmp1=std:: max(tmp1,rec[a[r]]);
}
tmp2=tmp1;
for (;l>q[i].l;) { l--;
rec[a[l]]+=b[a[l]];
tmp1=std:: max(tmp1,rec[a[l]]);
}
ans[q[i].id]=tmp1;
for (;l<pos;) {
rec[a[l]]-=b[a[l]]; l++;
}
tmp1=tmp2;
}
rep(i,1,m) printf("%lld\n", ans[i]);
return 0;
}