hdu4056Draw a Mess(线段树解法)
来源:互联网 发布:淘宝特卖会 编辑:程序博客网 时间:2024/05/22 19:27
题目请戳这里
题目大意:给一个n*m的矩形,有9中颜色,4种集合图形,q个操作,每个操作是将矩形中指定位置的某种几何形状的格子染相应的颜色。求最后9种颜色相应的数量。
题目分析:第一眼感觉就是线段树,一开始想的是写个二维的线段树,然后就在想怎么更新比较快。发现二维线段树除了更新矩形外对于其他3个图形的更新毫无优势。如果一行一行的更新,太慢了。一直在纠结怎样快速成段更新其他3种几何图像。最后1个小时决定敲一下,敲了一会也放弃了。还好没有继续敲。
这题官方题解给的是O(n*m)的线性做法。不过线段树也是可以做的。只是要写n棵线段树,而不是二维的!!其实写n棵线段树也容易爆内存的,何况二维的。再考虑到每次对一个格子涂色后就会覆盖上一次的颜色,所以每个格子最终的颜色取决于最后一次涂的颜色。所以要把查询倒着做!!涂过颜色的格子就删掉。这样线段树就比较容易完成了。不过效率并不是十分高,踩线过。。
唉,2道线段树,一道都没出,到现在了,还是这么弱啊。。。
详情请见代码:
#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int N = 201;const int M = 50001;struct nd{ char c; int p[5];}ask[M];int m,n,q;int ans[11];struct segt{ short int tree[M<<2]; void init(int num,int s,int e) { if(s == e) { tree[num] = 1; return; } int mid = (s + e)>>1; init(num<<1,s,mid); init(num<<1|1,mid + 1,e); tree[num] = tree[num<<1] + tree[num<<1|1]; } int query(int num,int s,int e,int l,int r) { if(s == l && e == r) return tree[num]; if(tree[num] == 0) return 0; int mid = (s + e)>>1; if(r <= mid) return query(num<<1,s,mid,l,r); else { if(l > mid) return query(num<<1|1,mid + 1,e,l,r); else return query(num<<1,s,mid,l,mid) + query(num<<1|1,mid + 1,e,mid + 1,r); } } void insert(int num,int s,int e,int l,int r) { if(s == l && e == r) { tree[num] = 0; return; } if(tree[num] == 0) return; int mid = (s + e)>>1; if(r <= mid) insert(num<<1,s,mid,l,r); else { if(l > mid) insert(num<<1|1,mid + 1,e,l,r); else { insert(num<<1,s,mid,l,mid); insert(num<<1|1,mid + 1,e,mid + 1,r); } } tree[num] = tree[num<<1] + tree[num<<1|1]; }}lcm[N];void Circle(int id){ int i,l,r; for(i = ask[id].p[0] + 1 - ask[id].p[2];i <= ask[id].p[0] + 1 + ask[id].p[2];i ++) { if(i < 1) continue; if(i > n) break; int tmp = (int)sqrt((double)(ask[id].p[2] * ask[id].p[2] - (i - ask[id].p[0] - 1) * (i - ask[id].p[0] - 1))); l = ask[id].p[1] + 1 - tmp; r = ask[id].p[1] + 1 + tmp; if(l < 1) l = 1; if(r > m) r = m; if(l > r) continue; tmp = lcm[i].query(1,1,m,l,r); if(tmp) { ans[ask[id].p[3]] += tmp; lcm[i].insert(1,1,m,l,r); } }}void Diamond(int id){ int i,l,r; for(i = ask[id].p[0] + 1 - ask[id].p[2];i <= ask[id].p[0] + 1 + ask[id].p[2];i ++) { if(i < 1) continue; if(i > n) break; l = ask[id].p[1] + 1 - ask[id].p[2] + abs(i - ask[id].p[0] - 1); r = ask[id].p[1] + 1 + ask[id].p[2] - abs(i - ask[id].p[0] - 1); if(l < 1) l = 1; if(r > m) r = m; if(l > r) continue; int tmp = lcm[i].query(1,1,m,l,r); if(tmp) { ans[ask[id].p[3]] += tmp; lcm[i].insert(1,1,m,l,r); } }}void Triangle(int id){ int i,l,r; int h = (ask[id].p[2] + 1)>>1; int cnt = 0; for(i = ask[id].p[0] + h;i >= ask[id].p[0] + 1;i --,cnt ++) { if(i > n) continue; l = ask[id].p[1] + 1 - cnt; r = ask[id].p[1] + 1 + cnt; if(l < 1) l = 1; if(r > m) r = m; int tmp = lcm[i].query(1,1,m,l,r); if(tmp) { ans[ask[id].p[3]] += tmp; lcm[i].insert(1,1,m,l,r); } }}void Rectangle(int id){ int i,l,r; l = ask[id].p[1] + 1; r = ask[id].p[1] + ask[id].p[3]; if(l > r) return; if(r > m) r = m; for(i = ask[id].p[0] + 1;i <= ask[id].p[0] + ask[id].p[2];i ++) { if(i > n) break; int tmp = lcm[i].query(1,1,m,l,r); if(tmp) { ans[ask[id].p[4]] += tmp; lcm[i].insert(1,1,m,l,r); } }}char op[12];int main(){ int i; while(scanf("%d",&n) != EOF) { scanf("%d%d",&m,&q); for(i = 1;i <= n;i ++) lcm[i].init(1,1,m); memset(ans,0,sizeof(ans)); for(i = 1;i <= q;i ++) { scanf("%s",op); ask[i].c = op[0]; for(int j = 0;j < 4;j ++) scanf("%d",&ask[i].p[j]); if(*op == 'R') scanf("%d",&ask[i].p[4]); } for(i = q;i >= 1;i --) { switch(ask[i].c) { case 'C':Circle(i);break; case 'D':Diamond(i);break; case 'T':Triangle(i);break; case 'R':Rectangle(i);break; } } for(i = 1;i < 9;i ++) printf("%d ",ans[i]); printf("%d\n",ans[i]); } return 0;}//4484MS53624K
- hdu4056Draw a Mess(线段树解法)
- HDU 1698 Just a Hook 线段树解法
- HDU3397Sequence operation线段树解法
- HUD1556 (树状数组解法+线段树解法)
- HDU 1540 Tunnel Warfare线段树解法及分块解法
- winform 如何绘制窗体? - what a mess
- hdc 4056 Draw a Mess(路径压缩)
- UVA1493 - Draw a Mess(并查集)
- Gym 100947I-What a Mess
- 校门外的树 线段树解法
- 线段树的应用-poj3264的解法
- 线段树的应用-poj3468的解法
- 线段树的应用-poj2777的解法
- 第一篇..poj3468 线段树解法
- RMQ问题的线段树解法
- HDOJ 敌兵布阵 (线段树解法)
- Spoj 375 Qtree 树链剖分 + 线段树 解法
- POJ 2828 Buy Tickets 线段树解法
- [UIPopoverController dealloc] reached while popover is still visible.'
- 找工作笔试面试那些事儿(7)---测试题答案
- papers
- 第五篇 STM-N帧结构
- mysql如何上传导入大文件sql
- hdu4056Draw a Mess(线段树解法)
- SEO优化
- ExtJs4.0环境搭建及spket安装 .
- 解决ubuntu下U盘变成只读的问题
- 避免网页加载速度慢的秘诀
- CCScene和CCLayer类详解
- document.body的一些用法以及js中的常见问题
- Android组件 概念
- MATLAB矩阵操作大全