cychester

Luogu3587[POI2015]POD - hash + 单调队列

Solution

还是去看了题解。 感谢大佬的博客→  题解传送门

是一道思路比较新的题。 

搞一个前缀和, 记录前 $i$ 个位置每种颜色的出现次数, 如果位置 $i$ 是 颜色 $a[i]$ 的最后一个位置, 就把颜色 $a[i]$ 清零。

这样就可以保证两个可以分割的点, 它们的前缀和一定是相同的。

$k$ 种颜色的前缀和不好维护(太大了), 就开到hash里面去, 用hash检验是否相等。

两个分割点 $r, l$ 要尽可能满足 $r-l$ 接近 $n \div 2$, 用单调队列维护

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define rd read()
 5 #define ll long long
 6 #define R register
 7 using namespace std;
 8 
 9 const int N = 1000005, base1 = 999979, base2 = 999983, mod1 = 1e9 + 7, mod2 = 1e9 + 9;
10 
11 ll po1[N], po2[N], sum1, sum2;
12 int last[N], cnt[N], n, k, a[N];
13 
14 struct node {
15     int id;
16     ll s1, s2;
17 }b[N];
18 
19 inline int read() {
20     int X = 0, p = 1; char c = getchar();
21     for (; c > '9' || c < '0'; c = getchar())
22         if (c == '-') p = -1;
23     for (; c >= '0' && c <= '9'; c = getchar())
24         X = X * 10 + c - '0';
25     return X * p;
26 }
27 
28 int cmp(const node &A, const node &B) {
29     if (A.s1 != B.s1) return A.s1 < B.s1;
30     if (A.s2 != B.s2) return A.s2 < B.s2;
31     return A.id < B.id;
32 }
33 
34 int jud(int x, int y) {
35     if (b[x].s1 != b[y].s1) return 0;
36     if (b[x].s2 != b[y].s2) return 0;
37     return 1;
38 }
39 
40 void cmin(int &A, int B) {
41     if (A > B) A = B;
42 }
43 
44 int Abs(int A) {
45     return A > 0 ? A : -A;
46 }
47 
48 int main()
49 {
50     n = rd; k = rd;
51     for (R int i = 1; i <= n; ++i)
52         a[i] = rd;
53     po1[0] = po2[0] = 1;
54     for (R int i = 1; i <= k; ++i)
55         po1[i] = po1[i - 1] * base1 % mod1,
56         po2[i] = po2[i - 1] * base2 % mod2;
57     for (R int i = 1; i <= n; ++i) 
58         cnt[a[i]]++, last[a[i]] = i;
59     for (R int i = 1; i <= n; ++i) {
60         (sum1 += po1[a[i]]) %= mod1;
61         (sum2 += po2[a[i]]) %= mod2;
62         if (i == last[a[i]]) 
63             sum1 = (sum1 - po1[a[i]] * cnt[a[i]] % mod1) % mod1,
64             sum1 = (sum1 + mod1) % mod1,
65             sum2 = (sum2 - po2[a[i]] * cnt[a[i]] % mod2) % mod2,
66             sum2 = (sum2 + mod2) % mod2;
67         b[i].id = i,
68         b[i].s1 = sum1,
69         b[i].s2 = sum2;
70     }
71     sort(b + 1, b + 1 + n, cmp);
72     ll ans1 = 0; int ans2 = n;
73     int mid = (n + 1) >> 1;
74     for (int i = 1, j = 1; i <= n; i = j) {
75         while (j <= n && jud(i, j)) j++;
76         ans1 += 1LL * (j - i) * (j - i - 1) / 2;
77         for (int l = i, r = i; r < j; ++r) {
78             while (l < r && b[r].id - b[l].id >= mid) l++;
79             cmin(ans2, Abs(n - 2 * (b[r].id - b[l].id)));
80             if (l != i) 
81                 cmin(ans2, Abs(n - 2 * (b[r].id - b[l - 1].id)));
82         }
83     }
84     printf("%lld %d\n", ans1, ans2);
85 }
View Code

 

posted on 2018-10-26 08:33  cychester  阅读(205)  评论(0编辑  收藏  举报

导航