Codeforces 527C 线段树 /set
2016-03-05 22:52
489 查看
题目:http://codeforces.com/problemset/problem/527/C
题意:
给出矩形的长和高,然后给出一些操作,水平或者竖直切割矩形,每切割一次,求出剩下的面积最大的矩形
分析:
看到题目,就想到是如何维护区间的最大值,第一想到的就是线段树,可以把还可以划线点的用1表示,划了线的用0表示,然后求最大长度就是如何求连续的1的最大个数,那么这题的变成了一道区间合并的问题了。那这道题集合hdu3667有点相似了,我的题解hdu 3667 ,区间合并需要注意的就是点和长度的区别,注意最后要加1.
线段树的非递归写法可参考这篇博客,我还是第一次见,不好理解啊http://blog.csdn.net/zearot/article/details/44759437
然而这题还有更多的人使用set和multiset去维护,挺简单的,学习一下。
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 formH y or
V x. In the first case Leonid makes the horizontal cut at the distancey 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 distancex (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.
Examples
Input
Output
Input
Output
Note
Picture for the first sample test:
![](http://codeforces.com/predownloaded/e2/bd/e2bda93feec87c1c28cc10ecbb413946855ba848.png)
Picture for the second sample test:
题意:
给出矩形的长和高,然后给出一些操作,水平或者竖直切割矩形,每切割一次,求出剩下的面积最大的矩形
分析:
看到题目,就想到是如何维护区间的最大值,第一想到的就是线段树,可以把还可以划线点的用1表示,划了线的用0表示,然后求最大长度就是如何求连续的1的最大个数,那么这题的变成了一道区间合并的问题了。那这道题集合hdu3667有点相似了,我的题解hdu 3667 ,区间合并需要注意的就是点和长度的区别,注意最后要加1.
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long ll; const int N=2e5+5; int lsum[N<<2][2],rsum[N<<2][2],sum[N<<2][2]; //分别维护区间左侧开始最多连续1的个数,右侧,和整个区间 bool pure[N<<2][2]; //标记是否整个区间都是连续1,其实这个数组不必要,只是为了方便 int t[2]; void pushUP(int rt,int id) { pure[rt][id]=pure[rt<<1][id]&&pure[rt<<1|1][id]; sum[rt][id]=max(rsum[rt<<1][id]+lsum[rt<<1|1][id],max(sum[rt<<1][id],sum[rt<<1|1][id])); lsum[rt][id]=pure[rt<<1][id]?lsum[rt<<1][id]+lsum[rt<<1|1][id]:lsum[rt<<1][id]; rsum[rt][id]=pure[rt<<1|1][id]?rsum[rt<<1|1][id]+rsum[rt<<1][id]:rsum[rt<<1|1][id]; } void build(int l,int r,int rt,int id) { if(l==r){ if(l==0)return; lsum[rt][id]=rsum[rt][id]=sum[rt][id]=pure[rt][id]=1; return; } int m=(l+r)>>1; build(lson,id); build(rson,id); pushUP(rt,id); } void update(int l,int r,int rt,int id,int p) { if(l==r&&l==p){ pure[rt][id]=sum[rt][id]=lsum[rt][id]=rsum[rt][id]=0; return; } int m=(l+r)>>1; if(p<=m)update(lson,id,p); else update(rson,id,p); pushUP(rt,id); } int main() { //freopen("f.txt","r",stdin); int w,h,n; scanf("%d%d%d",&w,&h,&n); build(0,w-1,1,0); build(0,h-1,1,1); char op[5]; int p; // cout<<sum[1][0]<<' '<<sum[1][1]<<endl; while(n--){ scanf("%s%d",op,&p); op[0]=='V'?update(0,w-1,1,0,p):update(0,h-1,1,1,p); //cout<<sum[1][0]<<' '<<sum[1][1]<<endl; printf("%I64d\n",(ll)(sum[1][0]+1)*(ll)(sum[1][1]+1)); } return 0; }
线段树的非递归写法可参考这篇博客,我还是第一次见,不好理解啊http://blog.csdn.net/zearot/article/details/44759437
然而这题还有更多的人使用set和multiset去维护,挺简单的,学习一下。
#include<iostream> #include<cstdio> #include<set> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; set<int>::iterator i,j; set<int>sw,sh; multiset<int>msw,msh; void update(set<int>&s,multiset<int>&ms,int p) { s.insert(p); i=j=s.find(p); --i;++j; ms.erase(ms.find(*j-*i)); //要这样删除一个元素 // ms.erase(*j-*i); //这样会把值相等的所有元素全删掉 ms.insert(p-*i); ms.insert(*j-p); } int main() { //freopen("f.txt","r",stdin); int ww,hh,n; scanf("%d%d%d",&ww,&hh,&n); sw.insert(0);sw.insert(ww); sh.insert(0);sh.insert(hh); msw.insert(ww); msh.insert(hh); char op[5]; int p; while(n--){ scanf("%s%d",op,&p); if(op[0]=='V'){ update(sw,msw,p); printf("%I64d\n",(ll)*(--msw.end())*(ll)(*(--msh.end()))); } else{ update(sh,msh,p); printf("%I64d\n",(ll)(*(--msw.end()))*(ll)(*(--msh.end()))); } // for(multiset<int>::iterator it=msw.begin();it!=msw.end();it++) // cout<<*it<<' '; // cout<<endl; } return 0; }
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 formH y or
V x. In the first case Leonid makes the horizontal cut at the distancey 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 distancex (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.
Examples
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:
![](http://codeforces.com/predownloaded/e2/bd/e2bda93feec87c1c28cc10ecbb413946855ba848.png)
Picture for the second sample test:
![](http://codeforces.com/predownloaded/d9/f5/d9f532b5567469e1431b3fb1a4aad1d786ddf2e5.png)
相关文章推荐
- Android使用 LruCache 缓存图片
- 第十四章编程练习(5)
- 三星NoteII美国V版I605,恢复三网以及3G上网的办法
- 大牛推荐的一些书籍,留着备用
- 基本I/O模型与Epoll简介
- IOC容器构造之加载和解析配置文件
- Objective-C 中 @property的使用
- Servlet中forword与include的区别
- lordofpomelo windows下安装问题总结
- 软件过程与项目管理(第二次作业)
- 一个由INode节点爆满引起的业务故障 推荐
- 加密器,对自己的文件加密
- Android 第三天重置版_注意事项
- hdu 5635 LCP Array(BC第一题)
- Ignatius and the Princess IV
- LeetCode 69 Sqrt(x)(Math、Binary Search)(*)
- 【类库】私房干货.Net数据层方法的封装
- 观察者模式与事件驱动模式实例比较
- HDU 1031 Design T-Shirt(结构体2级排序)
- 希尔排序