Description
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 1output
8
4
4
2input
7 6 5
H 4
V 3
V 5
H 2
V 1output
28
16
12
6
4
Note
Picture for the first sample test:
Picture for the second sample test:
Stantard Report
Obviously the largest glass piece at any moment is the one that is product of the largest horizontal segment by the largest vertical segment. One of the possible solutions is to carefully implement what described in the statement and keep all horizontal segments and all vertical segments in priority queue or std::set, or some logarithmic data structure. This solution works in .
But there is also a nice linear solution if we answer all queries in reverse order. Suppose segments are not cutting, but merging. In this case we may keep the horizontal and vertical cut lines in double-linked lists and track the current maximum (that can only increase and become equal to the newly-merged segment each time). This solution works in O(k + n + m).
My Problem Report
这道题要求每次切割过后剩下最大的玻璃块面积。这个问题可以转化为求每次切割后x轴上最长线段和y轴上最长险段。
最开始拿到这道题我想的是用两个堆和两个队列来维护,将当前先生与线段放入堆,将需要处理的命令放入队列。每次当队头元素在堆顶区间内时,才将队头弹出。后来再一想,这样的方法是大错特错的。因为队头元素不是每次都是我们所需要的,有可能某一次堆顶元素的区间需要被切割时,切割操作还没有到达队头。
于是我开始重新审视这个问题。当进行每次切割时和查询,实际上我们只执行了三步操作:查找特定区间,插入,查找最大区间。这个时候我发现堆和队列都是不能实现特定区间(值)查找的,并且我们所围护的这一系列特定区间(值)不具有单调性,因此二分查找也不可行。
在logn时间内查找指定值,修改后重新插入,搜索二叉树恰好满足这样的要求。我们考虑用两个set来维护切割点,两个set来维护线段。因为set内部采用的是中序遍历,因此当我们插入一个切割点之后,该点前一个指针与后一个指针恰好与它相邻,于是我们可以很方便地计算出需要删除和添加的线段长度。
Code
// Created by Chlerry in 2015.
// Copyright (c) 2015 Chlerry. All rights reserved.
// http://codeforces.com/problemset/problem/527/C
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <sstream>
using namespace std;
multiset<long long> a[2];
multiset<long long> ha[2];
multiset<long long>::iterator it,i0,i1;
void Output();
int main()
{
//freopen("in.txt","r",stdin);
long long w,h,temp,l,r;
int n;
char ch[2];
cin>>w>>h>>n;
a[0].insert(0);a[0].insert(w);ha[0].insert(w);
a[1].insert(0);a[1].insert(h);ha[1].insert(h);
while(n--)
{
cin>>ch>>temp;
bool flag=(ch[0]=='H');
//cout<<ch<<' '<<temp<<endl;
a[flag].insert(temp);
it=a[flag].find(temp);
l=temp-*(--it);
r=*(++++it)-temp;
it=ha[flag].find(l+r);
ha[flag].erase(it);//Wrong ha[flag].erase(l+r);
ha[flag].insert(l);
ha[flag].insert(r);
i0=ha[0].end();
i1=ha[1].end();
//Output();
cout<<(*(--i0))*(*(--i1))<<endl;
}
return 0;
}
void Output()
{
cout<<"W: ";
for(it=ha[0].begin();it!=ha[0].end();it++)
cout<<*it<<" ";
cout<<endl;
cout<<"V: ";
for(it=ha[1].begin();it!=ha[1].end();it++)
cout<<*it<<" ";
cout<<endl;
}