Skip to content

Instantly share code, notes, and snippets.

@ruslanjan
Created March 6, 2018 09:28
Show Gist options
  • Select an option

  • Save ruslanjan/a1b9846ce7714cba3e157a32118549af to your computer and use it in GitHub Desktop.

Select an option

Save ruslanjan/a1b9846ce7714cba3e157a32118549af to your computer and use it in GitHub Desktop.
//
// Created by Ruslan Jankurazov.
// Copyright © 2018 Ruslan Jankurazov. All rights reserved.
//
#pragma GCC optimize("Ofast")
#include "bits/stdc++.h"
#define pb push_back
#define mp make_pair
#define ll long long
#define ull unsigned long long
#define f first
#define s second
#define uint unsigned int
using namespace std;
int a[500500];
map <int, int> m;
int c = 0;
int last[500500];
int last2[500500];
int dp[500500];
mt19937 mt(42*42);
uniform_int_distribution<> dist(0, 1e5);
struct Node {
int x, y;
Node *l, *r;
int sz = 1;
Node (int x):x(x) {
l = r = nullptr;
y = dist(mt);
}
};
int sz(Node *t) {
return t?t->sz:0;
}
void upd(Node *t) {
if (t)
t->sz = 1 + sz(t->l) + sz(t->r);
}
void merge(Node *&t, Node *l, Node *r) {
if (!l || !r)
t = l?l:r;
else {
if (l->y > r->y) {
t = l;
merge(t->r, l->r, r);
} else {
t = r;
merge(t->l, l, r->l);
}
}
upd(t);
}
void split(Node *t, int x, Node *&l, Node *&r) {
if (!t)
l = r = nullptr;
else {
if (t->x >= x) {
r = t;
split(t->l, x, l, r->l);
} else {
l = t;
split(t->r, x, l->r, r);
}
}
upd(l);
upd(r);
}
void splitsz(Node *t, int x, Node *&l, Node *&r) {
if (!t)
l = r = nullptr;
else {
int i = 1 + sz(t->l);
if (i > x) {
r = t;
splitsz(t->l, x, l, r->l);
} else {
l = t;
splitsz(t->r, x - i, l->r, r);
}
}
upd(l);
upd(r);
}
int t[500500 * 4];
int tl[500500 * 4];
int get(int *t, int v, int l, int r, int ql, int qr) {
if (l > qr || r < ql)
return 0;
if (ql <= l && r <= qr)
return t[v];
int m = (l + r)>>1;
return get(t, v*2, l, m, ql, qr) + get(t, v*2+1, m + 1, r, ql, qr);
}
void upd(int *t, int v, int l, int r, int i, int val) {
if (l == r) {
t[v] += val;
} else {
int m = (l + r)>>1;
if (i <= m)
upd(t, v*2, l, m, i, val);
else
upd(t, v*2 + 1, m + 1, r, i, val);
t[v] = t[v*2] + t[v*2+1];
}
}
int main() {
#define FILE_INPUT 0
#define FILE ""
#ifndef DEBUG
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
#if FILE_INPUT == 1
#warning "FREOPEN is on"
freopen(FILE".in", "r", stdin);
freopen(FILE".out", "w", stdout);
#endif
#endif
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
if (!m.count(a[i]))
m[a[i]] = c++;
a[i] = m[a[i]];
}
if (n <= 5000) {
int last = 0;
ll ans = 0;
for (int i = 1; i <= n; ++i) {
set <int> e;
e.insert(a[i]);
set <int> s;
int len = 1;
for (int j = i - 1; j >= i - last; --j) {
if (e.find(a[j]) != e.end()) {
e.erase(a[j]);
s.insert(a[j]);
} else if (s.find(a[j]) == s.end())
e.insert(a[j]);
if (e.empty())
break;
len++;
}
last = len;
ans += len;
}
cout << ans;
return 0;
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
int len = 1;
if (last[a[i]] == 0)
len = dp[i - 1] + 1;
else {
len = dp[i - 1] + 1;
if (last[a[i]] + 1 == i)
len = 1;
else if (dp[i - 1] + 1 >= i - last[a[i]] + 1) {
len = dp[i - 1] + 1;
if (get(t, 1, 1, n, i - len + 1, i) - 1 == 0) {
len = i - last[a[i]] + 1;
}
}
}
dp[i] = len;
ans += len;
if (last2[a[i]] > 0)
upd(t, 1, 1, n, last2[a[i]], 1);
last2[a[i]] = last[a[i]];
if (last[a[i]] > 0)
upd(t, 1, 1, n, last2[a[i]], -2);
last[a[i]] = i;
upd(t, 1, 1, n, last[a[i]], 1);
}
cout << ans;
return 0;
}
/*
5
2 1 2 1 1
_ 2 1 2 1 1
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment