[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. QRadioButton分组且无边框的简单实现

    最近在用QT+VS2008做一个项目,涉及到一个综合测评表,说白了有点像问卷调查——很多题目每题若干个选项. 初始时打算用下拉框,每个框中填入所有选项,但后来一琢磨这种方式不够直观与人性化,增添了一步 ...

  2. ArcGIS中的北京54和西安80投影坐标系详解

    ArcGIS中的北京54和西安80投影坐标系详解 1.首先理解地理坐标系(Geographic coordinate system),Geographic coordinate system直译为地理 ...

  3. 大型网站系统架构实践(五)深入探讨web应用高可用方案

    从上篇文章到这篇文章,中间用了一段时间准备,主要是想把东西讲透,同时希望大家给与一些批评和建议,这样我才能有所进步,也希望喜欢我文章的朋友,给个赞,这样我才能更有激情,呵呵. 由于本篇要写的内容有点多 ...

  4. 琐碎--选择文件夹(路径)+生产txt格式的log+数据库操作方式

    记录日常工作常用到的一些方法: 1 选择文件操作,并将文件的路径记录下来: OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = f ...

  5. JavaScript基础---语言基础(4)

    函数,对象和数组 学习要点: 1.函数声明 2.return返回值 3.arguments对象 4.Object类型 5.Array类型 6.对象中的方法 函数是定义一次但却可以调用或执行任意多次的一 ...

  6. AngularJS开发指南9:AngularJS作用域的详解

    AngularJS作用域是一个指向应用模型的对象.它是表达式的执行环境.作用域有层次结构,这个层次和相应的DOM几乎是一样的.作用域能监控表达式和传递事件. 作用域的特点 作用域提供APIs($wat ...

  7. try throw catch异常处理机制

    /*本程序实现分块查找算法  又称索引顺序查找     需要注意的是分块查找需要2次查找  先对块查找  再对块内查找    2013.12.16    18:44*/ #include <io ...

  8. tomcat 简介

    一,Tomcat简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项 ...

  9. DEDECMS数据库执行原理、CMS代码层SQL注入防御思路

    我们在上一篇文章中学习了DEDECMS的模板标签.模板解析原理,以及通过对模板核心类的Hook Patch来对模板的解析流量的攻击模式检测,达到修复模板类代码执行漏洞的目的 http://www.cn ...

  10. POJ2677 Tour(DP+双调欧几里得旅行商问题)

    Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3929   Accepted: 1761 Description ...