Cod sursa(job #1993976)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 24 iunie 2017 04:52:06
Problema Secventa 5 Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.1 kb
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cassert>
#include <map>
#include <set>
#include <climits>
#include <cmath>
#include <list>
#include <functional>
#include <unordered_set>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef unsigned int uint;

#ifdef INFOARENA
#define ProblemName "secv5"
#endif

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

struct node {
	int val;
	node *left, *right;
	node(int v, node *L = NULL, node *R = NULL) : val(v), left(L), right(R) {}
};

#define MAXN 1058576
node *arb[MAXN];
int N, L, U;
map<uint, int> lastPos;

inline int val(node *n) {
	return n ? n->val : 0;
}
inline node *leftChild(node *n) {
	return n ? n->left : NULL;
}
inline node *rightChild(node *n) {
	return n ? n->right : NULL;
}

node *insert(node *root, int pos, int v, int left, int right) {
	if (left == right) return new node(v);
	if (left > right) return NULL;
	int mid = left + (right - left) / 2;
	if (pos <= mid) {
		node *t = insert(leftChild(root), pos, v, left, mid);
		return new node(val(t) + val(rightChild(root)), t, rightChild(root));
	}
	else {
		node *t = insert(rightChild(root), pos, v, mid + 1, right);
		return new node(val(leftChild(root)) + val(t), leftChild(root), t);
	}
}

int qL, qR;

int _query(node *root, int left, int right) {
	if (right < qL || left > qR)
		return 0;
	if (qL <= left && right <= qR)
		return val(root);
	int mid = left + (right - left) / 2;
	return _query(leftChild(root), left, mid) +  _query(rightChild(root), mid + 1, right);
}

int query(node *root, int left, int right) {
	qL = left, qR = right;
	return _query(root, 1, N);
}

int binSrch(int l, int k) {
	//first r from l such that in (l, r) there are k distinct
	int left = l, right = N;
	int found = N + 1;
	while (left <= right) {
		int mid = left + (right - left) / 2;
		int d = query(arb[mid], l, mid);
		if (d >= k) {
			if (d == k)
				found = mid;
			right = mid - 1;
		}
		else left = mid + 1;
	}
	return found;
}

int answer(int l) {
	int iL = binSrch(l, L);
	if (iL == N)
		return 0;
	int iR = binSrch(l, U + 1);
	//fprintf(stderr, "%d : %d %d\n", l, iL, iR);
	return iR - iL;
}

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OuFile, "w", stdout));
	scanf("%d%d%d", &N, &L, &U);
	arb[0] = NULL;
	for (int i = 1; i <= N; ++i) {
		uint a;
		scanf("%u", &a);
		int lp = lastPos[a];
		if (lp == 0)
			arb[i] = insert(arb[i - 1], i, 1, 1, N);
		else
			arb[i] = insert(insert(arb[i - 1], lp, 0, 1, N), i, 1, 1, N);
		lastPos[a] = i;
	}
	lastPos.clear();
	/*LL ans = 0;
	for (int i = 1; i <= N; ++i)
	for (int j = i; j <= N; ++j) {
		int r = query(arb[j], i, j);
		if (r >= L && r <= U)
			++ans;
		//fprintf(stderr, "%2d %2d : %2d\n", i, j, query(arb[j], i, j));
	}*/
	LL ans = 0;
	for (int i = 1; i <= N; ++i)
		ans += answer(i);
	printf("%lld\n", ans);
	return 0;
}