[codeforces 528]A. Glass Carving

试题描述

Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular wmm  ×  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?

输入

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.

输出

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

输入示例

H
V
V
V

输出示例


数据规模及约定

见“输入

题解

不难发现对于任意的长、宽,我们都可以还原出原玻璃板上的一个矩形,所以求最大面积可以转化为分别求最大的长和宽,然后乘起来就是答案。

问题变成了一个一维的:每次在 [0, n] 这个区间内插入不重复的点并询问最长的不包含任何点的线段。不难想到平衡树,因为它可以维护一个点的前驱和后继(不妨设这是平衡树 1 号),那么如何实时维护最长线段呢?我们可以再建一棵平衡树(平衡树 2 号)维护每条线段的长度,那么一次插入操作(插入点 x)不仅要在 1 号中插入一个数并找到其前驱 l 和后继 r,还要在 2 号中删除 r - l 这个长度,并添加 x - l 和 r - x 这两个长度,维护最大值即可。因为要分别维护矩形的长和宽,所以总共要建立 4 棵平衡树。(感觉好有毒。。。)

对于其他人,这题是 STL 水题;对于我,这题是数据结构码农题。。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 1000010
#define LL long long
int n, m, q; struct Node {
int v, r, mn, mx;
Node(): v(0), r(0), mn(0), mx(0) {}
Node(int _, int __, int ___, int ____): v(_), r(__), mn(___), mx(____) {}
} ns[maxn];
int r1, r2, r3, r4, ch[maxn][2], fa[maxn], ToT;
void maintain(int o) {
int l = ch[o][0], r = ch[o][1];
ns[o].mn = ns[o].mx = ns[o].v;
if(l) ns[o].mn = min(ns[o].mn, ns[l].mn), ns[o].mx = max(ns[o].mx, ns[l].mx);
if(r) ns[o].mn = min(ns[o].mn, ns[r].mn), ns[o].mx = max(ns[o].mx, ns[r].mx);
return ;
}
void rotate(int u) {
int y = fa[u], z = fa[y], l = 0, r = 1;
if(ch[y][1] == u) swap(l, r);
if(z) ch[z][ch[z][1]==y] = u;
fa[u] = z; fa[y] = u; fa[ch[u][r]] = y;
ch[y][l] = ch[u][r]; ch[u][r] = y;
maintain(y); maintain(u);
return ;
}
int xl, xr;
void insert(int& o, int v) {
if(!o) ns[o = ++ToT] = Node(v, rand(), v, v);
else {
int d = (v >= ns[o].v);
// printf("%d %d %d\n", ns[o].v, v, ns[ch[o][d]].mn);
// printf("%d %d %d\n", ns[ch[o][d]].mx, v, ns[o].v);
if(v >= ns[o].v && v <= ns[ch[o][d]].mn) xl = max(xl, ns[o].v), xr = min(xr, ns[ch[o][d]].mn);
if(v <= ns[o].v && v >= ns[ch[o][d]].mx) xl = max(xl, ns[ch[o][d]].mx), xr = min(xr, ns[o].v);
insert(ch[o][d], v);
fa[ch[o][d]] = o;
// printf("bo: %d %d\n", o, ch[o][d]);
if(ns[ch[o][d]].r > ns[o].r) {
int t = ch[o][d];
rotate(ch[o][d]);
o = t;
}
// printf("ao: %d\n", o);
}
return maintain(o);
}
bool del(int& o, int v, int pa) {
if(!o) return 1;
// printf("del: %d %d %d\n", o, ns[o].v, v);
if(ns[o].v == v) {
if(!ch[o][0] && !ch[o][1]) {
fa[o] = ch[o][0] = ch[o][1] = 0, o = 0;
maintain(o);
return 0;
}
if(!ch[o][0]) {
int t = ch[o][1];
fa[o] = ch[o][0] = ch[o][1] = 0, o = t, fa[o] = pa;
maintain(o);
return 0;
}
if(!ch[o][1]) {
int t = ch[o][0];
fa[o] = ch[o][0] = ch[o][1] = 0, o = t, fa[o] = pa;
maintain(o);
return 0;
}
int d = ns[ch[o][1]].r > ns[ch[o][0]].r;
int t = ch[o][d];
rotate(ch[o][d]);
o = t;
del(ch[o][d^1], v, o);
maintain(o);
return 0;
}
int d = (v >= ns[o].v);
if(del(ch[o][d], v, o)) maintain(o), del(ch[o][d^1], v, o);
maintain(o);
return 0;
} int main() {
srand(6);
n = read(); m = read(); q = read(); insert(r1, 0); insert(r1, m);
insert(r2, 0); insert(r2, n);
insert(r3, m); insert(r4, n);
while(q--) {
char tp = getchar();
while(!isalpha(tp)) tp = getchar();
int x = read();
xl = -1; xr = max(n, m) + 1;
if(tp == 'H') {
insert(r1, x);
int l = xl, r = xr;
// printf("f %d %d\n", l, r);
del(r3, r - l, 0);
insert(r3, x - l), insert(r3, r - x);
}
if(tp == 'V') {
insert(r2, x);
int l = xl, r = xr;
// printf("f %d %d\n", l, r);
del(r4, r - l, 0);
insert(r4, x - l), insert(r4, r - x);
}
printf("%I64d\n", (LL)ns[r3].mx * ns[r4].mx);
} return 0;
}

[codeforces 528]A. Glass Carving的更多相关文章

  1. codeforces 527 C Glass Carving

    Glass Carving time limit per test 2 seconds Leonid wants to become a glass carver (the person who cr ...

  2. 【codeforces 527C】Glass Carving

    [题目链接]:http://codeforces.com/contest/527/problem/C [题意] 让你切割一个长方形; 只能横切或竖切; 让你实时输出切完之后最大的长方形的面积; [题解 ...

  3. Codeforces 527C Glass Carving

    vjudge 上题目链接:Glass Carving 题目大意: 一块 w * h 的玻璃,对其进行 n 次切割,每次切割都是垂直或者水平的,输出每次切割后最大单块玻璃的面积: 用两个 set 存储每 ...

  4. Codeforces 527C Glass Carving(Set)

    意甲冠军  片w*h玻璃  其n斯普利特倍  各事业部为垂直或水平  每个分割窗格区域的最大输出 用两个set存储每次分割的位置   就能够比較方便的把每次分割产生和消失的长宽存下来  每次分割后剩下 ...

  5. Codeforces Round #296 (Div. 1) A. Glass Carving Set的妙用

    A. Glass Carving time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  6. Codeforces Round #296 (Div. 2) C. Glass Carving [ set+multiset ]

    传送门 C. Glass Carving time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  7. Glass Carving CodeForces - 527C (线段树)

    C. Glass Carving time limit per test2 seconds memory limit per test256 megabytes inputstandard input ...

  8. CF #296 (Div. 1) A. Glass Carving 线段树

    A. Glass Carving time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  9. [codeforces 528]B. Clique Problem

    [codeforces 528]B. Clique Problem 试题描述 The clique problem is one of the most well-known NP-complete ...

随机推荐

  1. Customizing Navigation Bar and Status Bar

    Like many of you, I have been very busy upgrading my apps to make them fit for iOS 7. The latest ver ...

  2. git查看某个文件的修改历史及具体修改内容

    有时候在比对代码时,看到某些改动,但不清楚这个改动的作者和原因,也不知道对应的BUG号,也就是说无从查到这些改动的具体原因了- [注]:某个文件的改动是有限次的,而且每次代码修改的提交都会有commi ...

  3. asp.net 捕获全局未处理异常的几种方法

    通过HttpModule来捕获未处理的异常[推荐] 首先需要定义一个HttpModule,并监听未处理异常,代码如下: public void Init(HttpApplication context ...

  4. iOS开发小技巧--UIScrollView内部子控件添加约束的注意点

    注意:用UIScrollView时布局子控件的时候,不要相对于UIScrollView来添加约束,这样做不是设置子控件的位置,反而是设置了UIScrollView的contentSize 子控件的尺寸 ...

  5. 使用X-UA-Compatible来设置IE浏览器兼容模式

    文件兼容性用于定义让IE如何编译你的网页.此文件解释文件兼容性,如何指定你网站的文件兼容性模式以及如何判断一个网页该使用的文件模式. 前言 为了帮助确保你的网页在所有未来的IE版本都有一致的外观,IE ...

  6. You've got to find what you love

    你必须找到你爱的东西 You've got to find what you love 史蒂夫乔布斯2005年6月在斯坦福大学毕业典礼上的演讲 I am honored to be with you ...

  7. 最短路之Dijkstra算法

    1. 邻接矩阵 int cost[MAX_V][MAX_V]; //assume cost[u][v]>0 int d[MAX_V]; bool used[MAX_V]; void Dijkst ...

  8. Linux下J2EE环境搭建

    1.下载MyEclipse 2010的linux安装包. myeclipse-10.1-offline-installer-linux 2.将下载MyEclipse 2010的linux安装包,使用X ...

  9. TFS 配置 报表权限问题

    通过[项目门户网站]访问,却被提示ReportService权限不足时, 提示:处理报表时出错. (rsProcessingAborted)  对数据集 “dsiteration” 执行查询失败 同样 ...

  10. 刨根问底拦不住——I/O模型

    前言 看过很多资料,很多对I/O模型概念模糊甚至错误,希望这篇文章有助理解I/O,欢迎讨论和纠正 参考资料:<UNIX网络编程卷1>  P122 I/O中涉及概念 介绍阻塞非阻塞,同步异步 ...