C. Glass Carving

time limit per test2 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular w mm  ×  h mm sheet of glass, a diamond glass cutter and lots of enthusiasm. What he lacks is understanding of what to carve and how.

In order not to waste time, he decided to practice the technique of carving. To do this, he makes vertical and horizontal cuts through the entire sheet. This process results in making smaller rectangular fragments of glass. Leonid does not move the newly made glass fragments. In particular, a cut divides each fragment of glass that it goes through into smaller fragments.

After each cut Leonid tries to determine what area the largest of the currently available glass fragments has. Since there appear more and more fragments, this question takes him more and more time and distracts him from the fascinating process.

Leonid offers to divide the labor — he will cut glass, and you will calculate the area of the maximum fragment after each cut. Do you agree?

Input

The first line contains three integers w, h, n (2 ≤ w, h ≤ 200 000, 1 ≤ n ≤ 200 000).

Next n lines contain the descriptions of the cuts. Each description has the form H y or V x. In the first case Leonid makes the horizontal cut at the distance y millimeters (1 ≤ y ≤ h - 1) from the lower edge of the original sheet of glass. In the second case Leonid makes a vertical cut at distance x (1 ≤ x ≤ w - 1) millimeters from the left edge of the original sheet of glass. It is guaranteed that Leonid won't make two identical cuts.

Output

After each cut print on a single line the area of the maximum available glass fragment in mm2.

Examples

inputCopy

4 3 4

H 2

V 2

V 3

V 1

outputCopy

8

4

4

2

inputCopy

7 6 5

H 4

V 3

V 5

H 2

V 1

outputCopy

28

16

12

6

4

Note

Picture for the first sample test:

Picture for the second sample test:

题意:

给你一个矩阵,和q个询问,每个询问可以横着切或者竖着切,问你切之后剩下完整的的矩阵中面积最大的是多大?

思路:

线段树可以维护最长连续0.

我们可以按行和列建立2个线段树,

点的信息为0或者1,0代表没有被切,1代表已经被切。

,每一次查询行和列的最大连续0,行列加1后乘起来即是最大的矩阵面积。

为什么要加1?

我们01序列表示的是每一个点是否被切割,而矩阵转成点线的问题可以这样处理:

即有n行每一行m列小方块,那么转成点线(方便线段树处理)就建立为 1~n-1 行,1~m-1列

查询的时候+1 就是方格个数。

接下来我们看如何用线段树维护区间最长连续零的个数。

我们每一个区间维护这四个信息:

1、从左开始最长的连续零个数 (记为 Rnum)

2、从右开始最长连续零个数 ( 记为 Lnum)

3、区间最长连续零的个数、(记为num)

4、本区间是否全为0 (其实可以用3与区间的长度判断得出,但是多维护一个减少代码量。)

从儿子节点更新父节点:

1、从左开始最长连续零的个数:

如果左儿子全是0,则为左儿子的num+ 右儿子的Lnum

否则为 左儿子的Lnum

2、从右开始最长连续零的个数:

如果右儿子全是0,则为右儿子的num+ 左儿子的Rnum

否则为 右儿子的Rnum

3、区间最长连续零的个数:

max(左儿子的Lnum,右儿子的Rnum,左儿子的Rnum+右儿子的Lnum )

4、本区间是否全为0

  1. 最容易维护,判断左右儿子是否都全为0即可。

细节见代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <queue>
  7. #include <stack>
  8. #include <map>
  9. #include <set>
  10. #include <vector>
  11. #include <iomanip>
  12. #define ALL(x) (x).begin(), (x).end()
  13. #define sz(a) int(a.size())
  14. #define all(a) a.begin(), a.end()
  15. #define rep(i,x,n) for(int i=x;i<n;i++)
  16. #define repd(i,x,n) for(int i=x;i<=n;i++)
  17. #define pii pair<int,int>
  18. #define pll pair<long long ,long long>
  19. #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
  20. #define MS0(X) memset((X), 0, sizeof((X)))
  21. #define MSC0(X) memset((X), '\0', sizeof((X)))
  22. #define pb push_back
  23. #define mp make_pair
  24. #define fi first
  25. #define se second
  26. #define eps 1e-6
  27. #define gg(x) getInt(&x)
  28. #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
  29. using namespace std;
  30. typedef long long ll;
  31. ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
  32. ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
  33. ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
  34. inline void getInt(int* p);
  35. const int maxn = 200200;
  36. const int inf = 0x3f3f3f3f;
  37. /*** TEMPLATE CODE * * STARTS HERE ***/
  38. struct node
  39. {
  40. int l,r;
  41. int isall;
  42. int num;
  43. int lm;
  44. int rm;
  45. };
  46. node segment_tree1[maxn<<2];
  47. node segment_tree2[maxn<<2];
  48. void pushup(node * segment_tree,int rt)
  49. {
  50. if(segment_tree[rt<<1].isall)
  51. {
  52. segment_tree[rt].isall=(segment_tree[rt<<1|1].isall);
  53. segment_tree[rt].num=segment_tree[rt<<1].lm+segment_tree[rt<<1|1].lm;
  54. segment_tree[rt].lm=segment_tree[rt<<1].lm+segment_tree[rt<<1|1].lm;
  55. if(segment_tree[rt<<1|1].isall)
  56. {
  57. segment_tree[rt].rm=segment_tree[rt<<1|1].num+segment_tree[rt<<1].rm;
  58. }else
  59. {
  60. segment_tree[rt].rm=segment_tree[rt<<1|1].rm;
  61. }
  62. }else if(segment_tree[rt<<1|1].isall)
  63. {
  64. segment_tree[rt].isall=(segment_tree[rt<<1].isall);
  65. segment_tree[rt].num=segment_tree[rt<<1|1].rm+segment_tree[rt<<1].rm;
  66. segment_tree[rt].rm=segment_tree[rt<<1|1].rm+segment_tree[rt<<1].rm;
  67. if(segment_tree[rt<<1].isall)
  68. {
  69. segment_tree[rt].lm=segment_tree[rt<<1|1].num+segment_tree[rt<<1].lm;
  70. }else
  71. {
  72. segment_tree[rt].lm=segment_tree[rt<<1].lm;
  73. }
  74. }else
  75. {
  76. segment_tree[rt].isall=0;
  77. segment_tree[rt].lm=segment_tree[rt<<1].lm;
  78. segment_tree[rt].rm=segment_tree[rt<<1|1].rm;
  79. segment_tree[rt].num=max(max(segment_tree[rt].lm,segment_tree[rt].rm),segment_tree[rt<<1].rm+segment_tree[rt<<1|1].lm);
  80. segment_tree[rt].num=max(segment_tree[rt].num,segment_tree[rt<<1].num);
  81. segment_tree[rt].num=max(segment_tree[rt].num,segment_tree[rt<<1|1].num);
  82. }
  83. }
  84. void build(node * segment_tree,int rt,int l,int r)
  85. {
  86. segment_tree[rt].l=l;
  87. segment_tree[rt].r=r;
  88. if(l==r)
  89. {
  90. segment_tree[rt].isall=1;
  91. segment_tree[rt].lm=1;
  92. segment_tree[rt].rm=1;
  93. segment_tree[rt].num=1;
  94. return;
  95. }
  96. int mid=(l+r)>>1;
  97. build(segment_tree,rt<<1,l,mid);
  98. build(segment_tree,rt<<1|1,mid+1,r);
  99. pushup(segment_tree,rt);
  100. }
  101. int ask(node * segment_tree)
  102. {
  103. return segment_tree[1].num;
  104. }
  105. void update(node * segment_tree,int rt,int x)
  106. {
  107. if(segment_tree[rt].l==segment_tree[rt].r&&segment_tree[rt].l==x)
  108. {
  109. segment_tree[rt].isall=0;
  110. segment_tree[rt].lm=0;
  111. segment_tree[rt].rm=0;
  112. segment_tree[rt].num=0;
  113. }else
  114. {
  115. int mid=(segment_tree[rt].l+segment_tree[rt].r)>>1;
  116. if(x<=mid)
  117. {
  118. update(segment_tree,rt<<1,x);
  119. }else
  120. {
  121. update(segment_tree,rt<<1|1,x);
  122. }
  123. pushup(segment_tree,rt);
  124. }
  125. }
  126. int main()
  127. {
  128. //freopen("D:\\code\\text\\input.txt","r",stdin);
  129. //freopen("D:\\code\\text\\output.txt","w",stdout);
  130. int n,m;
  131. int q;
  132. scanf("%d %d %d",&n,&m,&q);
  133. build(segment_tree1,1,1,m-1);
  134. build(segment_tree2,1,1,n-1);
  135. while(q--)
  136. {
  137. char op;
  138. getchar();
  139. scanf("%c",&op);
  140. if(op=='H')
  141. {
  142. int x;
  143. scanf("%d",&x);
  144. update(segment_tree1,1,x);
  145. }else
  146. {
  147. int x;
  148. scanf("%d",&x);
  149. update(segment_tree2,1,x);
  150. }
  151. ll ans=(ask(segment_tree2)+1ll);
  152. ans*=(ask(segment_tree1)+1ll);
  153. printf("%lld\n",ans );
  154. }
  155. return 0;
  156. }
  157. inline void getInt(int* p) {
  158. char ch;
  159. do {
  160. ch = getchar();
  161. } while (ch == ' ' || ch == '\n');
  162. if (ch == '-') {
  163. *p = -(getchar() - '0');
  164. while ((ch = getchar()) >= '0' && ch <= '9') {
  165. *p = *p * 10 - ch + '0';
  166. }
  167. }
  168. else {
  169. *p = ch - '0';
  170. while ((ch = getchar()) >= '0' && ch <= '9') {
  171. *p = *p * 10 + ch - '0';
  172. }
  173. }
  174. }

Glass Carving CodeForces - 527C (线段树)的更多相关文章

  1. Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论

    Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变 ...

  2. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem E (Codeforces 831E) - 线段树 - 树状数组

    Vasily has a deck of cards consisting of n cards. There is an integer on each of the cards, this int ...

  3. Codeforces 938G 线段树分治 线性基 可撤销并查集

    Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问 ...

  4. codeforces 1136E 线段树

    codeforces 1136E: 题意:给你一个长度为n的序列a和长度为n-1的序列k,序列a在任何时候都满足如下性质,a[i+1]>=ai+ki,如果更新后a[i+1]<ai+ki了, ...

  5. Z - New Year Tree CodeForces - 620E 线段树 区间种类 bitset

    Z - New Year Tree CodeForces - 620E 这个题目还没有写,先想想思路,我觉得这个题目应该可以用bitset, 首先这个肯定是用dfs序把这个树转化成线段树,也就是二叉树 ...

  6. D - The Bakery CodeForces - 834D 线段树优化dp···

    D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...

  7. B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路

    B - Legacy CodeForces - 787D 这个题目开始看过去还是很简单的,就是一个最短路,但是这个最短路的建图没有那么简单,因为直接的普通建图边太多了,肯定会超时的,所以要用线段树来优 ...

  8. CodeForces 343D 线段树维护dfs序

    给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u ...

  9. Linear Kingdom Races CodeForces - 115E (线段树优化dp)

    大意: n条赛道, 初始全坏, 修复第$i$条花费$a_i$, m场比赛, 第$i$场比赛需要占用$[l_i,r_i]$的所有赛道, 收益为$w_i$, 求一个比赛方案使得收益最大. 设$dp[i]$ ...

随机推荐

  1. 【CUDA开发】Thrust库

    Thrust库从C++的STL中得到灵感,将最简单的类似于STL的结构放在Thrust库中,比如STL中的vector.此外,Thrust库还包含STL中的算法和迭代器.        Thrust函 ...

  2. powerDesigner连接数据库连接失败

    powerDesigner连接数据库总是提示连接失败 原因是这个软件不能使用64位的jdk只能使用32位的jdk 在软件安装文件夹根目录下创建start.bat Set JAVA_HOME=E:\Ja ...

  3. mysql 速度优化

    1.添加索引 ALTER TABLE `cw_base_house` ADD INDEX idx_house ( `villageCode`, `buildingNo`, `unitNo`, `hou ...

  4. ideal中运行manven常用操作

    ideal中对项目打包,输入命令如下图所示: clean install -Dmaven.test.skip=true

  5. 【转帖】GBase 数据库

    产品介绍 分析型数据管理系统 GBase 8a GBase 8a能够实现大数据的全数据(结构化数据.半结构化数据和非结构化数据)存储管理和高效分析,为行业大数据应用提供完整的数据库解决方案.GBase ...

  6. Spread.NET 表格控件 V12.0 Update2 发布更新

    Spread.NET表格控件V12.0 Update 2 已经正式发布,本次发布主要针对WinForm平台下客户反馈的产品使用功能进行优化,并修复了已知问题,具体修复情况见下方说明. Spread.N ...

  7. 解决The total number of locks exceeds the lock table size错误

    参考:https://blog.csdn.net/weixin_40683253/article/details/80762583 mysql在进行大批量的数据操作时,会报“The total num ...

  8. Mysql workbench 字段类型(转载)

    转载自:https://blog.csdn.net/j_h_xie/article/details/52924521 项目初始,在使用workbench建表时,字段中有PK,NN,UQ,BIN,UN, ...

  9. # Excel批量处理数据

    Excel批量处理数据 拖住框下拉即可得到每行+3的结果

  10. 字符串转数组(php版)

    思路: 1.判断当前传来的值是否为数组 2.若不是现将传来的值转换为字符串类型 3.判断当前值是否为空 4.若不为空,采用正则进行匹配,如下图 preg_match('/^{.*?}$/', $str ...