4384: [POI2015]Trzy wieże

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 217  Solved: 61
[Submit][Status][Discuss]

Description

给定一个长度为n的仅包含'B'、'C'、'S'三种字符的字符串,请找到最长的一段连续子串,使得这一段要么只有一种字符,要么有多种字符,但是没有任意两种字符出现次数相同。

Input

第一行包含一个正整数n(1<=n<=1000000),表示字符串的长度。
第二行一个长度为n的字符串。

Output

包含一行一个正整数,即最长的满足条件的子串的长度。

Sample Input

9
CBBSSBCSC

Sample Output

6

HINT

选择BSSBCS这个子串。

Source

[Submit][Status][Discuss]

分析

OTZ Claris

OTZ LincHpin

OTZ MirrorGray

——下面开始正文——

子串只包含一种字符的情况特殊处理,一遍扫描就可以了。

首先将字符串转换称数字串,分别用0,1,2替代B,C,S。

设sum[i][j]表示前i(0<=i<=n)个数字中j(0<=j<=2)的出现次数,则题目要求可以翻译如下

选取一段[lt + 1, rt],满足:

sum[rt][0] - sum[lt][0] != sum[rt][1] - sum[lt][1]

sum[rt][0] - sum[lt][0] != sum[rt][2] - sum[lt][2]

sum[rt][1] - sum[lt][1] != sum[rt][2] - sum[lt][2]

从Claris大神那里学到的机智转换——通过交换等式两边的元素,将lt和rt分离。

sum[rt][0] - sum[rt][1] != sum[lt][0] - sum[lt][1]

sum[rt][0] - sum[rt][2] != sum[lt][0] - sum[lt][2]

sum[rt][1] - sum[rt][2] != sum[lt][1] - sum[lt][2]

这看起来就神清气爽多了,问题就转换成了——

每个点上有一个三元组(x,y,z),以及一个id,求对于每个点来说,和它的三元组完全不同的id相距最远的点。

将(x,y,z,id)按照x从小到大排序,这样就可以保证x的不同了。

然后把y当作树状数组下标维护id的最大、最小值,这样查询的时候避开自己y的地方就可以保证y也不同了。

可以z还可能相同,所以要维护次优解,且强制最优解和次优解的z不同。当最优解的z和当前点的z相同时,选择用次优解来更新即可。这样就保证z也不同了。

然而并不清楚Claris大神是怎么用64行写完的,但也不代表我写200+行就有多麻烦,至少不是很费脑子(才怪)。

代码

  1. #include <bits/stdc++.h>
  2.  
  3. const int N = ;
  4. const int inf = 1e9 + ;
  5.  
  6. int n, m;
  7.  
  8. int h[N];
  9.  
  10. char s[N];
  11.  
  12. int sum[];
  13.  
  14. int answer;
  15.  
  16. struct Point
  17. {
  18. int id, x, y, z;
  19.  
  20. Point(void) {};
  21. Point(int i, int a, int b, int c)
  22. {
  23. id = i;
  24. x = a;
  25. y = b;
  26. z = c;
  27. }
  28.  
  29. friend bool operator < (const Point &a, const Point &b)
  30. {
  31. return a.x < b.x;
  32. }
  33. }p[N];
  34.  
  35. struct Pair
  36. {
  37. int val, pos;
  38.  
  39. Pair(void) {};
  40.  
  41. Pair(int a, int b)
  42. {
  43. val = a;
  44. pos = b;
  45. }
  46.  
  47. friend bool operator ^ (const Pair &a, const Pair &b)
  48. {
  49. return a.pos != b.pos;
  50. }
  51.  
  52. friend bool operator < (const Pair &a, const Pair &b)
  53. {
  54. return a.val < b.val;
  55. }
  56.  
  57. friend bool operator > (const Pair &a, const Pair &b)
  58. {
  59. return a.val > b.val;
  60. }
  61. };
  62.  
  63. struct MinMax
  64. {
  65. Pair min0;
  66. Pair min1;
  67. Pair max0;
  68. Pair max1;
  69.  
  70. MinMax(void)
  71. {
  72. min0 = Pair(inf, -inf);
  73. min1 = Pair(inf, -inf);
  74. max0 = Pair(-inf, -inf);
  75. max1 = Pair(-inf, -inf);
  76. }
  77.  
  78. MinMax(int val, int pos)
  79. {
  80. min0 = max0 = Pair(val, pos);
  81. min1 = Pair(inf, -inf);
  82. max1 = Pair(-inf, -inf);
  83. }
  84.  
  85. friend MinMax operator + (const MinMax &a, const MinMax &b)
  86. {
  87. MinMax r;
  88.  
  89. if (a.min0 < b.min0)
  90. {
  91. r.min0 = a.min0;
  92. if (a.min1 < b.min0)
  93. r.min1 = a.min1;
  94. else if (a.min0 ^ b.min0)
  95. r.min1 = b.min0;
  96. else if (a.min1 < b.min1)
  97. r.min1 = a.min1;
  98. else
  99. r.min1 = b.min1;
  100. }
  101. else
  102. {
  103. r.min0 = b.min0;
  104. if (b.min1 < a.min0)
  105. r.min1 = b.min1;
  106. else if (a.min0 ^ b.min0)
  107. r.min1 = a.min0;
  108. else if (b.min1 < a.min1)
  109. r.min1 = b.min1;
  110. else
  111. r.min1 = a.min1;
  112. }
  113.  
  114. if (a.max0 > b.max0)
  115. {
  116. r.max0 = a.max0;
  117. if (a.max1 > b.max0)
  118. r.max1 = a.max1;
  119. else if (a.max0 ^ b.max0)
  120. r.max1 = b.max0;
  121. else if (a.max1 > b.max1)
  122. r.max1 = a.max1;
  123. else
  124. r.max1 = b.max1;
  125. }
  126. else
  127. {
  128. r.max0 = b.max0;
  129. if (b.max1 > a.max0)
  130. r.max1 = b.max1;
  131. else if (a.max0 ^ b.max0)
  132. r.max1 = a.max0;
  133. else if (b.max1 > a.max1)
  134. r.max1 = b.max1;
  135. else
  136. r.max1 = a.max1;
  137. }
  138.  
  139. return r;
  140. }
  141. };
  142.  
  143. struct BIT
  144. {
  145. MinMax tree[N];
  146.  
  147. int lowbit(int x)
  148. {
  149. return x & -x;
  150. }
  151.  
  152. MinMax query(int p)
  153. {
  154. MinMax r;
  155.  
  156. while (p)
  157. {
  158. r = r + tree[p];
  159. p -= lowbit(p);
  160. }
  161.  
  162. return r;
  163. }
  164.  
  165. void insert(int p, MinMax v)
  166. {
  167. while (p <= m)
  168. {
  169. tree[p] = tree[p] + v;
  170. p += lowbit(p);
  171. }
  172. }
  173. }lt, rt;
  174.  
  175. signed main(void)
  176. {
  177. scanf("%d%s", &n, s + );
  178.  
  179. for (int i = , j = ; i <= n; ++i)
  180. {
  181. if (s[i] == s[i - ])
  182. answer = std::max(answer, ++j);
  183. else
  184. answer = std::max(answer, j = );
  185. }
  186.  
  187. for (int i = ; i <= n; ++i)
  188. {
  189. switch (s[i])
  190. {
  191. case 'B': ++sum[]; break;
  192. case 'C': ++sum[]; break;
  193. case 'S': ++sum[]; break;
  194. }
  195.  
  196. p[i] = Point(
  197. i,
  198. sum[] - sum[],
  199. sum[] - sum[],
  200. sum[] - sum[]
  201. );
  202.  
  203. h[i] = p[i].y;
  204. }
  205.  
  206. p[++n] = Point(, , , );
  207.  
  208. std::sort(p + , p + + n);
  209. std::sort(h + , h + + n);
  210.  
  211. m = std::unique(h + , h + + n) - h - ;
  212.  
  213. for (int i = ; i <= n; ++i)
  214. p[i].y = std::lower_bound(h + , h + + m, p[i].y) - h;
  215.  
  216. for (int i = , j = ; i <= n; i = j)
  217. {
  218. while (j <= n && p[i].x == p[j].x)++j;
  219.  
  220. for (int k = i; k < j; ++k)
  221. {
  222. MinMax l = lt.query(p[k].y - );
  223. MinMax r = rt.query(m - p[k].y);
  224.  
  225. if (l.min0.pos != p[k].z)
  226. answer = std::max(answer, p[k].id - l.min0.val);
  227. else
  228. answer = std::max(answer, p[k].id - l.min1.val);
  229.  
  230. if (l.max0.pos != p[k].z)
  231. answer = std::max(answer, l.max0.val - p[k].id);
  232. else
  233. answer = std::max(answer, l.max1.val - p[k].id);
  234.  
  235. if (r.min0.pos != p[k].z)
  236. answer = std::max(answer, p[k].id - r.min0.val);
  237. else
  238. answer = std::max(answer, p[k].id - r.min1.val);
  239.  
  240. if (r.max0.pos != p[k].z)
  241. answer = std::max(answer, r.max0.val - p[k].id);
  242. else
  243. answer = std::max(answer, r.max1.val - p[k].id);
  244. }
  245.  
  246. for (int k = i; k < j; ++k)
  247. {
  248. lt.insert(p[k].y, MinMax(p[k].id, p[k].z));
  249. rt.insert(m + - p[k].y, MinMax(p[k].id, p[k].z));
  250. }
  251. }
  252.  
  253. printf("%d\n", answer);
  254. }

BZOJ_4384.cpp

@Author: YouSiki

BZOJ 4384: [POI2015]Trzy wieże的更多相关文章

  1. [POI2015]Trzy wieże

    [POI2015]Trzy wieże 题目大意: 给定一个长度为\(n(n\le10^6)\)的仅包含'B'.'C'.'S'三种字符的字符串,请找到最长的一段连续子串,使得在这一段内出现过的所有字符 ...

  2. 【BZOJ4384】[POI2015]Trzy wieże 树状数组

    [BZOJ4384][POI2015]Trzy wieże Description 给定一个长度为n的仅包含'B'.'C'.'S'三种字符的字符串,请找到最长的一段连续子串,使得这一段要么只有一种字符 ...

  3. BZOJ4384 : [POI2015]Trzy wieże

    首先只有一种字符的情况可以通过双指针在$O(n)$的时间内处理完毕. 设$cnt[i][j]$表示前$i$个字符中$j$字符出现的次数,那么对于两个位置$j<i$: 如果 $cnt[i][0]- ...

  4. bzoj 4386: [POI2015]Wycieczki

    bzoj 4386: [POI2015]Wycieczki 这题什么素质,爆long long就算了,连int128都爆……最后还是用long double卡过的……而且可能是我本身自带大常数吧,T了 ...

  5. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

  6. Bzoj 3747: [POI2015]Kinoman 线段树

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 553  Solved: 222[Submit][Stat ...

  7. BZOJ 3747 POI2015 Kinoman 段树

    标题效果:有m点,每个点都有一个权值.现在我们有这个m为点的长度n该序列,寻求区间,它仅出现一次在正确的点区间内值和最大 想了很久,甚至神标题,奔说是水的问题--我醉了 枚举左点 对于每个请求留点右键 ...

  8. BZOJ 4380 [POI2015]Myjnie | DP

    链接 BZOJ 4380 题面 有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]. 有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个 ...

  9. BZOJ 3747 POI2015 Kinoman

    因为上午没有准备够题目,结果发现写完这道题没题可写了QAQ 又因为这道题范围是100w,我写了发线段树,以为要T,上午就花了一个小时拼命卡常数 结果下午一交居然过了QAQ 我们考虑枚举L,求最大R使得 ...

随机推荐

  1. Centos5, 6下更改系统时间和时区

    http://www.namhuy.net/2435/how-to-change-date-time-timezone-on-centos-6.html 查看日期(使用 -R 参数会以数字显示时区) ...

  2. PAT 1021. 个位数统计 (15)

    给定一个k位整数N = dk-1*10k-1 + ... + d1*101 + d0 (0<=di<=9, i=0,...,k-1, dk-1>0),请编写程序统计每种不同的个位数字 ...

  3. EEG: electrode positions & Broadmann atlas

    Source: http://www.brainm.com/software/pubs/dg/BA_10-20_ROI_Talairach/nearesteeg.htm   Area LEFT RIG ...

  4. DEDECMS之七 如何实现文章推荐排行榜

    经常可以看到各种排行榜,这些文章列表的标题之前加了序号,前三条还有显眼样式 1.实现效果 2.实现方法 <ul class="hotPh1"> {dede:arclis ...

  5. git push ERROR: missing Change-Id in commit message footer

    今天上传代码时候报告错误:$ git push origin HEAD:refs/for/branch*Counting objects: 7, done.Delta compression usin ...

  6. QT QDateTime类、QTimer类

    QDateTime类,头文件#include <QDateTime> 可以使用QDateTime类来获得系统时间.通过QDateTime::currentDateTime()来获取本地系统 ...

  7. 纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!

    前言 FineUI控件库发展至今已经有 5 个年头,目前论坛注册的QQ会员 5000 多人,捐赠用户 500 多人(捐赠用户转化率达到10%以上,在国内开源领域相信这是一个梦幻数字!也足以证明Fine ...

  8. jQuery.uploadify-----文件上传带进度条,支持多文件上传的插件

    借鉴别人总结的uploadify:基于jquery的文件上传插件,支持ajax无刷新上传,多个文件同时上传,上传进行进度显示,控制文件上传大小,删除已上传文件. uploadify有两个版本,一个用f ...

  9. js正则表单验证汇总,邮箱验证,日期验证,电话号码验证,url验证,信用卡验证,qq验证

    本文主要汇总各种正则验证,很多都是转载,本人也会尽可能验证准确性,如有错误欢迎留言 //trim()方法在有些浏览器中不兼容,最好自己重写一下 String.prototype.trim=functi ...

  10. 4-pwd 打印当前工作目录

    pwd print name of current/working directory 打印当前工作目录 [语法]: pwd [选项] [参数] [功能介绍] pwd命令以绝对路径的方式显示用户当前工 ...