[FROM WOJ]#2443 L的鞋子

#2443 L的鞋子

题面
L是壕,他非常喜欢鞋子,他专门在他的别墅中修建了一个鞋柜,鞋柜是呈线性的,为了好找鞋子,他把他的鞋子分成了 c c 种。虽然L没有小学毕业,但是对数字非常偏爱,他很忌讳奇数,因为他觉得不吉利(壕都是这样的)。他想知道对于一个区间 [ l , r ] [l,r] 中,有多少种鞋子恰好出现正偶数次。
共有10组测试数据
1-4组 n , m = 500 2000 5000 10000 c = 1000 n,m=500,2000,5000,10000,c=1000
5-7组 n , m = 20000 30000 40000 c = 10000 n,m=20000,30000,40000,c=10000
8-10组 n , m = 50000 80000 100000 c = 100000 n,m=50000,80000,100000,c=100000
数据保证随机生成

输入
第一行 3 3 个整数, n n , c c , m m
第二行 n n 个数,每个数 A i Ai [ 1 , c ] [1,c] ,表示第 i i 双鞋子的样式
接下来 m m 行,每行2个整数 l l , r r ,表示询问 [ l , r ] [l,r] 的答案

输出
m m 行,回答答案

样例输入
5 5 3
1 1 2 2 3
1 5
3 4
2 3

样例输出
2
1
0

SOL
莫队模板题,离线分块做莫队, s [ i ] s[i] 记录第 i i 类鞋子的数量,用 s [ i ] s[i] 的变化统计 a n s ans
排序排两次。
第一次,以左端点所在块的编号为第一关键字,右端点为第二关键字。
第二次,以询问的原顺序排一次,恢复离线 s o l v e ( ) solve() 之前的答案顺序在输出。
完了。

代码:

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,m,c,k;
int a[N],b[N],s[N];
struct node{
	int l,r,ans,id;

}q[N];
inline bool comp(node s,node t){return (b[s.l]<b[t.l])||(b[s.l]==b[t.l] && s.r<t.r);}
inline bool cmp(node a,node b){return a.id<b.id;}
inline void solve(){
	int l=0,r=0,ans=0;
	for(int register i=1;i<=m;i++){
		while(r<q[i].r){
			r++;
			s[a[r]]++;//
			if(s[a[r]]%2==0)ans++;
			if(s[a[r]]%2==1&&s[a[r]]!=1)ans--; 
		}
		while(l>q[i].l){
			l--;
			s[a[l]]++;
			if(s[a[l]]%2==0)ans++;
			if(s[a[l]]%2==1&&s[a[l]]!=1)ans--; 
		}
		while(r>q[i].r){
			s[a[r]]--;//
			if(s[a[r]]%2==0&&s[a[r]]!=0)ans++;
			if(s[a[r]]%2==1)ans--; 
			r--;
		}
		while(l<q[i].l){
			s[a[l]]--;
			if(s[a[l]]%2==0&&s[a[l]]!=0)ans++;
			if(s[a[l]]%2==1)ans--;
			l++;
		}	
		q[i].ans=ans;
	}
}
int main(){
	scanf("%d%d%d",&n,&c,&m);k=sqrt(n);
	for(int register i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=(i-1)/k+1;
	}
	for(int register i=1;i<=m;i++){
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].id=i;
	}
	sort(q+1,q+m+1,comp);
	solve();
	sort(q+1,q+m+1,cmp);
	for(int register i=1;i<=m;i++)printf("%d\n",q[i].ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hzq_oi/article/details/87531535