Group HDU

//如果a[i]-1 和 a[i] + 1都没有维护过的话,那么就是多一个新串 
//如果 a[i] - 1和a[i] + 1 有一个被维护过了,那么接上就好
//如果 a[i] -1 和a[i] + 1 都被维护过了,那么把两个合成一个,就少一个串 
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
struct node{
	int L,R,id;
} ask[maxn];
int ans[maxn];
int a[maxn],num[maxn];//从1开始计数
int n,m,siz,temp;//n个数,m个询问,块的大小
bool cmp(node a,node b) {//分块排序 
	if(a.L/siz!=b.L/siz) 
		return a.L/siz<b.L/siz;
	else return a.R<b.R;
}
void sub(int pos) {
	int x=a[pos];
	num[x]=0;
	if(num[x-1]==0&&num[x+1]==0) 
		temp--;
	if(num[x-1]==1&&num[x+1]==1) 
		temp++;
}
void add(int pos) {
	int x=a[pos];
	num[x]=1;
	if(num[x-1]==0&&num[x+1]==0) 
		temp++;
	if(num[x-1]==1&&num[x+1]==1) 
		temp--;
}
void solve() {
	temp=0;
	memset(num,0,sizeof num);
	int L=1,R=0;
	for(int i=1; i<=m; i++) {
		while(R<ask[i].R) {
			R++;
			add(R);
		}
		while(R>ask[i].R) {
			sub(R);
			R--;
		}
		while(L<ask[i].L) {
			sub(L);
			L++;
		}
		while(L>ask[i].L) {
			L--;
			add(L);
		}
		ans[ask[i].id]=temp;
	}
}
int main() {
	int T;
	scanf("%d",&T);
	while(T--) 
	{
		scanf("%d%d",&n,&m);
		for(int i=1; i<=n; i++)
			scanf("%d",&a[i]);
		for(int i=1; i<=m; i++) {
			ask[i].id=i;
			scanf("%d%d",&ask[i].L,&ask[i].R);
		}
		siz=sqrt(n);
		sort(ask+1,ask+m+1,cmp);
		solve();
		for(int i=1; i<=m; i++)
			printf("%d
",ans[i]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12380360.html