有N个人站成一行,每个人有一个魅力值
相同魅力值的人会形成一个团伙,定义一个团伙正常当且仅当团伙人数为2
你的任务是回答M个询问,每次询问一个区间[LR]
你需要回答这个区间中所有人各自结成团伙后,处于不正常团伙中的人的魅力值之和
一句话题意:区间查询出现次数不为2的所有数字之和
一看到区间查询出现次数,我就想到了不修改莫队
一看到不修改莫队,我就想到了 [SDOI2009]HH的项链
一想到 [SDOI2009]HH的项链,我就想到这是道水题
我爱暴力数据结构,我爱莫队
(关于莫队的讲解,详见这篇博客:莫队学习笔记)
那么就是一道很简单的题了
代码:
#include<bits/stdc++.h>
#define ll long long
#define cont cnt[a[x]]
#define N 200005
using namespace std;
int n,m,a[N],belong[N],cnt[N];
int l=1,r=0;
ll now,ans[N];
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
struct Query
{
int l,r,id;
}q[N];
bool cmp(Query a,Query b)
{
return(belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r);
}
void update(int x,int opt)
{
if(!opt)
{
cont--;
if(cont==1) now+=a[x];
else if(cont==2) now-=a[x]*3;
else if(cont>=3) now-=a[x];
else now-=a[x];
}
else
{
cont++;
if(cont==2) now-=a[x];
else if(cont==3) now+=a[x]*cnt[a[x]];
else if(cont>=4) now+=a[x];
else now+=a[x];
}
return;
}
int main()
{
freopen("abnormal.in","r",stdin);
freopen("abnormal.out","w",stdout);
read(n);read(m);
int siz=sqrt(n);
for(register int i=1;i<=n;++i) read(a[i]);
for(register int i=1;i<=m;++i)
{
read(q[i].l);
read(q[i].r);
q[i].id=i;
}
for(register int i=1;i<=n;++i)
belong[i]=(i-1)/siz+1;//在第几个块
sort(q+1,q+m+1,cmp);
for(register int i=1;i<=m;++i)
{
while(l<q[i].l) update(l++,0);
while(l>q[i].l) update(--l,1);
while(r<q[i].r) update(++r,1);
while(r>q[i].r) update(r--,0);
ans[q[i].id]=now;
}
for(register int i=1;i<=m;++i) printf("%lld
",ans[i]);
return 0;
}
/*
5 5
4 3 3 4 1
1 1
1 4
1 2
1 5
2 3
*/