527C. Glass Carving【平衡二叉树】

C. Glass Carving
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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.

Sample test(s)
Input
4 3 4
H 2
V 2
V 3
V 1
Output
8
4
4
2
Input
7 6 5
H 4
V 3
V 5
H 2
V 1
Output
28
16
12
6
4
Note

Picture for the first sample test:

Picture for the second sample test:


题意:一个矩形,每次都可能横切一刀,或纵切一刀,每一次输出最大的块的面积。
分析:大神跟我说每次维护最长的高和最长的宽就好了,我一看,说的很简单,可是哪有那么容易啊。。。一开始想用队列,大神用的<set>容器,这是一个平衡二叉树。
先上代码吧
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
//527C  红黑二叉排序树

int main()
{
    int w,h,n;
    cin>>w>>h>>n;
    set<int >W,H;
    set<int >::iterator i,j;
    multiset <int >A,B;
    multiset <int >::iterator e1,e2;
    W.insert(0),W.insert(w);
    H.insert(0),H.insert(h);
    A.insert(h),B.insert(w);
    char ch;
    int a;
    while(n--)
    {
        cin>>ch>>a;
        if(ch=='H')
        {
            i=j=H.lower_bound(a);
            i--;
            H.insert(a);
            A.insert((*j)-a);
            A.insert(a-(*i));
            A.erase(A.find((*j)-(*i)));

        }
        else
        {
            i=j=W.lower_bound(a);
            i--;
            W.insert(a);
            B.insert((*j)-a);
            B.insert(a-(*i));
            B.erase(B.find((*j)-(*i)));

        }
        e1=A.end(),e2=B.end();
        e1--,e2--;
        long long int ans=((long long int)(*e1)*(*e2));
        cout<<ans;

    }
    return 0;
}

set和multiset的区别:set里不可以又重复的点。multiset可以。
lower_bound是二分遍历的意思。


set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值;另外,还得保证根节点左子树的高度与右子树高度相等。
平衡二叉检索树使用中序遍历算法,检索效率高于vector、deque和list等容器,另外使用中序遍历可将键值按照从小到大遍历出来。
构造set集合主要目的是为了快速检索,不可直接去修改键值。



这个题就是用W和H两个set,一个存储竖直方向的刀口位置,一个存储水平方向的刀口位置。
A和B两个set,分别存储最大的长度和最大的宽度。就是维护的这两个值。
每次切一刀,在H或Wset中插入刀口位置,在A或B中增添两个新的长度,因为一刀劈二分吗,删除原来的长度。set本身就是为我们排好序的,最后取出最后一个值就可以了。

你可能感兴趣的:(527C. Glass Carving【平衡二叉树】)