BZOJ 2084: [Poi2010]Antisymmetry

2084: [Poi2010]Antisymmetry

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 596  Solved: 379
[Submit][Status][Discuss]

Description

对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。
现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。

Input

第一行一个正整数N (N <= 500,000)。第二行一个长度为N的01字符串。

Output

一个正整数,表示反对称子串的个数。

Sample Input

8
11001011

Sample Output

7

hint
7个反对称子串分别是:01(出现两次), 10(出现两次), 0101, 1100和001011

HINT

Source

鸣谢 JZP

[Submit][Status][Discuss]

改版的Manacher,将判断条件改为两字符一个是‘0‘一个是‘1‘即可,最后用半径统计答案,莫名其妙的边界处理……

 1 #include <cstdio>
 2
 3 const int siz = 1000005;
 4
 5 int n;
 6 int s[siz];
 7 int r[siz];
 8 char str[siz];
 9
10 inline int min(int a, int b)
11 {
12     return a < b ? a : b;
13 }
14
15 inline bool check(int a, int b)
16 {
17     return
18         (a == 0 && b == 1)
19     ||  (a == 1 && b == 0)
20     ||  (a == 3 && b == 3);
21 }
22
23 signed main(void)
24 {
25     scanf("%d%s", &n, str + 1);
26
27     /*<--- Prework --->*/
28
29
30     for (int i = 1; i <= n; ++i)
31     {
32         static int tot = 0;
33         s[++tot] = 3;
34         s[++tot] = str[i] - ‘0‘;
35     }
36
37     n = 2*n + 1;
38
39     s[n] = 3;
40     s[0] = 4;
41     s[n + 1] = 4;
42
43     /*<--- Manacher --->*/
44
45     for (int i = 1; i <= n; i += 2)
46     {
47         static int maxi = 0, id = 0;
48
49         if (i <= maxi)
50             r[i] = min(maxi - i + 1, r[2*id - i]);
51         else
52             r[i] = 1;
53
54         while (check(s[i + r[i]], s[i - r[i]]))
55             ++r[i];
56
57         if (maxi < r[i] + i - 1)
58             maxi = r[i] + i - 1, id = i;
59     }
60
61     /*<--- Calculate --->*/
62
63     long long ans = 0LL;
64
65     for (int i = 1; i <= n; i += 2)
66         ans += (r[i] - 1) >> 1;
67
68     printf("%lld\n", ans);
69 }

@Author: YouSiki

时间: 2024-08-09 14:47:58

BZOJ 2084: [Poi2010]Antisymmetry的相关文章

bzoj 2084: [Poi2010]Antisymmetry -- manacher

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MB Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. Input 第一行一个正整数N (N <= 500,000).第二行一个长度为N的01字符串. Output

BZOJ 2084 [Poi2010]Antisymmetry(manacher)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2084 [题目大意] 对于一个01字符串,如果将这个字符串0和1取反后, 再将整个串反过来和原串一样,就称作“反对称”字符串. 比如00001111和010101就是反对称的,1001就不是. 现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. [题解] 修改manacher的判定条件,对该串进行计算即可. [代码] #include <cstdio> #include

BZOJ 2084 Poi2010 Antisymmetry Manacher算法

题目大意:给定一个长度为n的01串,问有多少个子串满足翻转并取反后和原来一样 定义0=1,0≠0,1≠1,跑Manacher即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 using namespace std; int n; char s[M]; long long Manacher(char str[],in

BZOJ2084: [Poi2010]Antisymmetry

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 187  Solved: 125[Submit][Status] Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. Input 第一行一个正整数

【bzoj2084】[Poi2010]Antisymmetry

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1205  Solved: 756[Submit][Status][Discuss] Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作"反对称"字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的.

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

BZOJ 2086: [Poi2010]Blocks

2086: [Poi2010]Blocks Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 494  Solved: 222[Submit][Status][Discuss] Description 给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1.经过一定次数的操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数

BZOJ 2080: [Poi2010]Railway 双栈排序

2080: [Poi2010]Railway Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 140  Solved: 35[Submit][Status][Discuss] Description 一个铁路包含两个侧线1和2,右边由A进入,左边由B出去(看下面的图片) 有n个车厢在通道A上,编号为1到n,它们被安排按照要求的顺序(a1,a2,a3,a4....an)进入侧线,进去还要出来,它们要按照编号顺序(1,2,3,4,5....n)从通道B

bzoj 2084

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2084 这道题很容易想到就是一个变种的最长回文字串, 不过回文的规则变成了s[i + p[i]] + s[i - p[i]] == 1 可以用hash 来nlogn, 不过最优是用manacher, 然后有一个非常迷的查空位的方法(' '       ) 可以看代码 #include <iostream> #include <cstring> #include <algo