[BZOJ 3521] [POI 2014] Bar

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 3521] [POI 2014] Bar相关的知识,希望对你有一定的参考价值。

题意

  有一个长度为 n , 由 p 和 j 构成的字符串 S .

  请你找到最长的子串 T , 满足 T 的任意一个前缀和任意一个后缀的 p 都比 j 多.

  n <= 1000000 .

 

分析

  建立平面直角坐标系, X 轴表示 p 的个数, Y 轴表示 j 的个数, 那么 S 的每个前缀可以在平面上被刻画出来.

 

  设 exR[i] 为以 i 开头的子串, 最多能延伸多少位.

  设 exL[i] 为以 i 结尾的子串, 最多能多少位.

  l, r 能满足, 当且仅当 r <=exR[l] 且 exL[r] <= l , 即两条线段相交.

  利用连续性优化, 我们利用扫描线 + 线段树.

 

  exL 与 exR 的求法类似, 如何求 exR ?

  过二维平面上的点 i , 作斜率为 1 的直线, 那么不能达到直线上方, 即不能碰到截距比当前大 1 的直线.

  找到截距比当前大 1 的直线上的 i 的后继 id , 那么 exR[i] = id-1 .

 

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <set>
 8 using namespace std;
 9 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
10 #define VI vector<int>::iterator
11 
12 const int N = 1000005;
13 const int S = 2500000;
14 
15 int n; char s[N];
16 int x[N], y[N]; vector<int> g[N+N];
17 int exL[N], exR[N];
18 vector<int> r[N]; int Max[S], ans;
19 
20 inline int own(int x, int y) { return y - x + n + 1; }
21 
22 #define Lc (x << 1)
23 #define Rc (x << 1 | 1)
24 #define M ((L + R) >> 1)
25 inline void Mod(int x, int L, int R, int pos, int sign) {
26     if (L == R) { Max[x] = (sign ? L : 0); return; }
27     pos <= M ? Mod(Lc, L, M, pos, sign) : Mod(Rc, M+1, R, pos, sign);
28     Max[x] = max(Max[Lc], Max[Rc]);
29 }
30 inline int Find(int x, int L, int R, int pos) {
31     // max_{x} (x <= pos)
32     if (pos < L) return 0;
33     if (R <= pos) return Max[x];
34     int tmp = Find(Rc, M+1, R, pos);
35     return tmp > 0 ? tmp : Find(Lc, L, M, pos);
36 }
37 
38 int main(void) {
39     #ifndef ONLINE_JUDGE
40         freopen("bar.in", "r", stdin);
41     #endif
42     
43     scanf("%d", &n), scanf("%s", s+1);
44     
45     g[own(0, 0)].push_back(0);
46     F(i, 1, n) {
47         x[i] = x[i-1], y[i] = y[i-1];
48         s[i] == p ? x[i]++ : y[i]++;
49         g[own(x[i], y[i])].push_back(i);
50     }
51     
52     F(i, 1, n) {
53         int u = own(x[i], y[i]) - 1;
54         VI it = lower_bound(g[u].begin(), g[u].end(), i);
55         exL[i] = (it == g[u].begin() ? 1 : *(--it) + 2);
56     }
57     F(i, 1, n) {
58         int u = own(x[i-1], y[i-1]) + 1;
59         VI it = lower_bound(g[u].begin(), g[u].end(), i);
60         exR[i] = (it == g[u].end() ? n : *it - 1);
61     }
62     
63     F(i, 1, n) if (exL[i] <= i) r[exL[i]].push_back(i);
64     F(i, 1, n) {
65         for (VI it = r[i].begin(); it != r[i].end(); it++)
66             Mod(1, 1, n, *it, 1);
67         if (i <= exR[i]) {
68             int id = Find(1, 1, n, exR[i]);
69             if (id > 0) ans = max(ans, id - i + 1);
70         }
71         Mod(1, 1, n, i, 0);
72     }
73     printf("%d\n", ans);
74     
75     return 0;
76 }

 

小结

  upper_bound 为大于 x 的最小的数.

  lower_bound 为大于等于 x 的最小的数.

  小于 x 的最小的数, 考虑 lower_bound - 1 .

  小于等于 x 的最小的数, 考虑 upper_bound - 1 .

以上是关于[BZOJ 3521] [POI 2014] Bar的主要内容,如果未能解决你的问题,请参考以下文章

LuoguP3521 [POI2011]ROT-Tree Rotations

P3521 [POI2011]ROT-Tree Rotations

P3521 [POI2011]ROT-Tree Rotations

Luogu P3521 [POI2011]ROT-Tree Rotations

题解 P3521 [POI2011]ROT-Tree Rotations

「Luogu P3521 [POI2011]ROT-Tree Rotations」