[20190925机房测试] 不正常团伙

有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
*/
原文地址:https://www.cnblogs.com/tqr06/p/11586981.html