Description
长度为
n
的一串项链,每颗珠子是
Solution
刚开始可能
Hash
函数太水了。。。数据大一点碰撞点太多。后来改成了双
Hash
函数。。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1010101;
const int M = 9999991;
const int P = 3628801;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
int n, k, F1, F2, m, p1, p2, ans1, d;
ll ans2;
int col[N], cnt[N], sd1[N], sd2[N], a[N];
struct Pair {
int h1, h2, id;
inline friend bool operator <(const Pair &a, const Pair &b) {
return a.h1 == b.h1 ? (a.h2 == b.h2 ? a.id < b.id : a.h2 < b.h2) : a.h1 < b.h1;
}
inline friend bool operator ==(const Pair &a, const Pair &b) {
return a.h1 == b.h1 && a.h2 == b.h2;
}
};
Pair Hash[N];
struct cpp {
int id[N];
inline int &operator [](const int &x) {
return id[x];
}
};
cpp id;
inline int Abs(int x) {
return x < 0 ? -x : x;
}
inline int Min(int a, int b) {
return a < b ? a : b;
}
int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
read(n); read(k); sd1[1] = sd2[1] = 1; ans1 = N;
for (int i = 1; i <= n; i++) {
read(col[i]); cnt[col[i]]++;
}
sd1[k] = 1; for (int i = k - 1; i; i--) sd1[i] = (ll)sd1[i + 1] * n % M;
sd2[k] = 1; for (int i = k - 1; i; i--) sd2[i] = (ll)sd2[i + 1] * n % P;
for (int i = 1; i <= k; i++) {
id[i] = 1;
F1 = (F1 + (ll)sd1[i]) % M;
F2 = (F2 + (ll)sd2[i]) % M;
}
for (int i = 1; i <= n; i++) {
cnt[col[i]]--;
F1 = (F1 - (ll)sd1[col[i]] * id[col[i]] % M) % M;
F2 = (F2 - (ll)sd2[col[i]] * id[col[i]] % P) % P;
if (!cnt[col[i]]) {
id[col[i]] = 1;
F1 = (F1 + M + sd1[col[i]]) % M;
F2 = (F2 + P + sd2[col[i]]) % P;
} else {
id[col[i]]++;
F1 = ((ll)sd1[col[i]] * id[col[i]]+ F1 + M) % M;
F2 = ((ll)sd2[col[i]] * id[col[i]]+ F2 + P) % P;
}
Hash[i].h1 = F1; Hash[i].h2 = F2; Hash[i].id = i;
}
sort(Hash + 1, Hash + n + 1);
for (int i = 1, j; i <= n; i = j + 1) {
for (j = i; Hash[j] == Hash[i]; j++); j--;
m = 0; for (int k = i; k <= j; k++) a[++m] = Hash[k].id;
if (m == 1) continue;
sort(a + 1, a + m + 1); ans2 += (ll)m * (m - 1) / 2;
for (int i = 1; i <= m; i++) a[i + m] = a[i] + n;
for (p1 = p2 = 1; p1 <= m; p1++) {
while (a[p1] + n - a[p2] >= a[p2] - a[p1] && p2 < p1 + m) {
d = Abs(a[p1] + n - a[p2] - a[p2] + a[p1]);
ans1 = Min(ans1, d); p2++;
}
}
}
cout << ans2 << ' ' << ans1 << endl;
return 0;
}