[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