CodeForces 527C(set大法好)
题目链接:CodeForces 527C
题目大意:
一块w*h的玻璃 对其进行n次切割 每次切割都是垂直或者水平的 输出每次切割后最大单块玻璃的面积。
第一行输入 w h n , 剩下n行每行一次cut , H 代表水平切, V 代表竖直切。
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
图形样例
第一组样例
第二组样例
思路
可以看出经过n次切割之后,剩余的最大面积就是剩余部分长的最大值 x 宽的最大值。 所以我们用两个multiset储存切割后的长宽即可。
如何计算长宽 ? 每次切,都要寻找切线两边的边界,这样才能计算出新的长或宽,以及删除旧的长或宽。我们用利用set中元素的有序性,再加上find 操作就很容易找到两边的元素了。
源代码
#include <iostream> #include <cstdio> #include <set> using namespace std; const int maxn = 200000 +10; int main(){ int w,h,q; set<int>sH; set<int>sW; multiset<int>mH; multiset<int>mW; while(scanf("%d%d%d",&w,&h,&q)!=EOF){ sH.clear();sW.clear(); mW.clear();mH.clear(); sH.insert(h);sH.insert(0); //管理边界的set先插入初始的边界 sW.insert(w);sW.insert(0); mH.insert(h);mW.insert(w); //管理长宽的multiset 先插入最大的长宽 char order; int pos; while(q--){ cin>>order>>pos; if(order == 'H'){ sH.insert(pos); //先将切线插入到对应位置 int a = *(--sH.find(pos)); //找到相邻切线 int b = *(++sH.find(pos)); // mH.erase(b-a); //这里注意不能这样 删除 ,否则就将所有元素中等于 b - a 的都删除了。 mH.erase(mH.find(b-a)); //在multiset中删除旧的长 或 宽。 // cout<<" "<<pos<<" "<< b<<" "<<a<<endl; mH.insert(b-pos); // 插入新的长或宽 mH.insert(pos-a); } else{ sW.insert(pos); int a = *(--sW.find(pos)); int b = *(++sW.find(pos)); // cout<<" "<<pos<<" "<< b<<" "<<a<<endl; // mW.erase(b-a); mW.erase(mW.find(b-a)); mW.insert(b-pos); mW.insert(pos-a); } printf("%I64d\n",(long long)*(--mW.end()) **(--mH.end())); //结果可能超int } } return 0; }