首页 > 代码库 > BZOJ 2743 HEOI 2012 采花 梳妆数组

BZOJ 2743 HEOI 2012 采花 梳妆数组

题目大意:给出一个序列,问一段序列中,出现两次以上的颜色有多少种。


思路:和HH的项链很像。

CODE:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1000010
using namespace std;

struct Ask{
	int x,y,_id;
	
	bool operator <(const Ask &a)const {
		return x < a.x;
	}
	void Read(int p) {
		scanf("%d%d",&x,&y);
		_id = p;
	}
}ask[MAX];

int cnt,cols,asks;
int fenwick[MAX];
int src[MAX];
int last[MAX],next[MAX];
int T[MAX];

int ans[MAX];

inline void Fix(int x,int c)
{
	if(!x)	return ;
	for(; x <= cnt; x += x&-x)
		fenwick[x] += c;
}

inline int GetSum(int x)
{
	int re = 0;
	for(; x; x -= x&-x)
		re += fenwick[x];
	return re;
}

int main()
{
	cin >> cnt >> cols >> asks;
	for(int i = 1; i <= cnt; ++i)
		scanf("%d",&src[i]);
	for(int i = 1; i <= cnt; ++i) {
		if(++T[src[i]] == 2)
			Fix(i,1);
		if(last[src[i]])
			next[last[src[i]]] = i;
		last[src[i]] = i;
	}
	for(int i = 1;i <= asks; ++i)
		ask[i].Read(i);
	sort(ask + 1,ask + asks + 1);
	ask[0].x = 1;
	for(int i = 1; i <= asks; ++i) {
		for(int j = ask[i - 1].x; j < ask[i].x; ++j) {
			Fix(next[j],-1);
			Fix(next[next[j]],1);
		}
		ans[ask[i]._id] = GetSum(ask[i].y);
	}
	for(int i = 1; i <= asks; ++i)
		printf("%d\n",ans[i]);
	return 0;
}


BZOJ 2743 HEOI 2012 采花 梳妆数组