题目链接:4241:历史研究
最近考莫队怎么考怎么挂……对莫队产生了一种莫名的感觉QAQ
于是我看见什么都觉得是莫队……
这是病得治……
比如说这道题,上来先写了一发莫队套线段树,时间复杂度直接T了……
放在这里当个板子吧,谁愿意看就看,愿意拖走就拖走,但是别交,我的线段树常数大极限数据21S……
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=101000;
struct seg{
int l,r;
LL mx,sum,num;
seg *lc,*rc;
seg():mx(0),sum(0),num(0){}
};
seg *root=new seg();
int n,m,N=0,pos[maxn],cnt=0;
struct ques{int l,r,id,p;}q[maxn];
struct point{int v,id;}b[maxn];
LL ans[maxn],a[maxn];
inline int read(){
int x=0,f=1;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;
}
bool cmp(const ques &a,const ques &b){
return (a.p<b.p||(a.p==b.p&&a.r<b.r));
}
void build(seg *p,int l,int r){
p->l=l; p->r=r;
if (l+1==r){
p->sum=0; p->num=a[l];
p->mx=0; p->lc=p->rc=NULL;
return;
}else if (l+1<r){
int mid=(l+r)>>1;
p->lc=new seg();
p->rc=new seg();
if (l<mid) build(p->lc,l,mid);
if (mid<r) build(p->rc,mid,r);
}
}
void push_up(seg *p){
if (p->l+1==p->r) return; p->mx=-1;
if (p->lc) p->mx=p->lc->mx;
if (p->rc) p->mx=max(p->mx,p->rc->mx);
}
void update(seg *p,int l,int r,int v){
if (l<=p->l&&p->r<=r){
p->sum+=v; p->mx=p->sum*p->num;
return;
}else{
int mid=(p->l+p->r)>>1;
if (l<mid&&p->lc) update(p->lc,l,r,v);
if (mid<r&&p->rc) update(p->rc,l,r,v);
push_up(p);
}
}
bool cmpb(const point &a,const point &b){
return a.v<b.v;
}
bool cmpid(const point &a,const point &b){
return a.id<b.id;
}
int main(){
scanf("%d%d",&n,&m); int blo=(int)sqrt(n);
for (int i=1;i<=n;++i)
b[i].v=read(),b[i].id=i;
sort(b+1,b+n+1,cmpb);
for (int i=1;i<=n;++i) {
if (b[i].v!=b[i-1].v) cnt++;
pos[b[i].id]=cnt; a[cnt]=b[i].v;
}
sort(b+1,b+n+1,cmpid);
build(root,1,cnt+1);
for (int i=1;i<=m;++i){
q[i].l=read(); q[i].r=read();
q[i].id=i; q[i].p=(q[i].l-1)/blo+1;
}
sort(q+1,q+m+1,cmp);
int l=q[1].l,r=q[1].l-1;
for (int i=1;i<=m;++i){
while (l>q[i].l) l--,update(root,pos[b[l].id],pos[b[l].id]+1,1);
while (r<q[i].r) r++,update(root,pos[b[r].id],pos[b[r].id]+1,1);
while (l<q[i].l) update(root,pos[b[l].id],pos[b[l].id]+1,-1),l++;
while (r>q[i].r) update(root,pos[b[r].id],pos[b[r].id]+1,-1),r--;
ans[q[i].id]=root->mx;
}
for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);
}