线段树扫描线hdu1828Picture
来源:互联网 发布:java colortorgb 编辑:程序博客网 时间:2024/05/01 01:39
线段树扫描线hdu1828Picture :http://acm.hdu.edu.cn/showproblem.php?pid=1828
思路:求矩形周长并……可以把矩形分成横线和竖线两部分,并将两条横线和两条竖线都分别标记为-1、1。然后建两遍数,将结果相加就可以了(也有其他建一遍树的做法)……但这个题值得说的就是用这种做法有一个坑……将矩形的横线和竖线的坐标按照从小到大(从大到小)的顺序排序,当两个矩形有边重合时得先把值为1(或-1)的边先加进去。如A矩形是【(0,0),(1,1)】,矩形B是【(1,0),(2,1)】,这样矩形A的右侧边和矩形B的左侧边重合了,假如我们规定左侧边标记为1,右侧边标记为-1,并且按从小到大排序,那么我们应该先把矩形B的左侧边先于A的右侧边加进去……这是因为如果先加A的右侧边,那么我们在pushup的时候先把标记加上了,此时对应的该标记为0了(1和-1抵消),这样sum就会被更新为0,这样会导致当前的sum和上一个sum间造成一个差值,从而导致A的右边和B的左边都重复计算……
在这里,我已经wa到死了……看了别人的写法发现和自己的就只有这里不同感觉很涨姿势,仔细想想才发现存在这样的差别……
#include<map>#include<cmath>#include<queue>#include<vector>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long LL;const int INF=0x3f3f3f3f;const double eps=1e-8;const int maxn=1e5+10;const int MAXM = 1e5+10;int cnt;struct Line { int val,u,v; int id; bool operator < (const Line &a)const { return val < a.val; }} lx[maxn*2],ly[maxn*2];int ans = 0;int sum[MAXM*2],vis[MAXM*2];void up(int l,int r,int rt) { if(vis[rt]) sum[rt] = r-l+1; else if(l == r) sum[rt] = 0; else sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void update(int L,int R,int id,int l,int r,int rt) { if(L <= l && r <= R) { vis[rt] += id; up(l,r,rt); return; } int m = l+r>>1; if(L <= m)update(L,R,id,lson); if(R > m)update(L,R,id,rson); up(l,r,rt);}void solve(int L,int R,struct Line *t) { memset(vis,0,sizeof(vis)); memset(sum,0,sizeof(sum)); int pre = 0; for(int i = 0; i < cnt; i++) { int l = t[i].u,r = t[i].v; update(l,r-1,t[i].id,L,R,1); ans += abs(pre-sum[1]); pre = sum[1]; }}int main() {// freopen("in.txt","r",stdin); int n,x1,x2,y1,y2; while(scanf("%d",&n) != EOF) { if(n == 0) { printf("0\n"); continue; } cnt = 0; ans = 0; for(int i = 0; i < n; i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1 += 10001,x2 += 10001,y1 += 10001,y2 += 10001; lx[i].val = y1,lx[i].u = x1,lx[i].v = x2,lx[i].id = 1; lx[i+n].val = y2,lx[i+n].u = x1,lx[i+n].v = x2,lx[i+n].id = -1; // 以前是这样写的: // lx[cnt].val = y1,lx[cnt].u = x1,lx[cnt].v = x2,lx[cnt].id = 1; // lx[cnt+1].val = y2,lx[cnt+1].u = x1,lx[cnt+1].v = x2,lx[cnt+1].id = -1; // 这样就使得A的右侧边先于B的左侧边加进去了,影响了排序的结果 ly[i].val = x1,ly[i].u = y1,ly[i].v = y2,ly[i].id = 1; ly[i+n].val = x2,ly[i+n].u = y1,ly[i+n].v = y2,ly[i+n].id = -1; } cnt = 2*n; sort(lx,lx+cnt); sort(ly,ly+cnt); memset(vis,0,sizeof(vis)); memset(sum,0,sizeof(sum)); solve(0,20001,lx); solve(0,20001,ly); printf("%d\n",ans); } return 0;}
0 0
- 线段树扫描线hdu1828Picture
- hdu1828Picture(线段树求矩形周长并)
- 线段树[扫描线]
- 线段树+扫描线
- 线段树 扫描线
- 线段树扫描线
- 线段树-扫描线
- hdu4007 线段树扫描线
- poj2482 线段树扫描线
- poj2464 线段树扫描线
- ural1707 线段树扫描线
- hdu4419 线段树扫描线
- hdu1828线段树+扫描线
- POJ1177+线段树+扫描线
- POJ1151+线段树+扫描线
- HDU3255(线段树+扫描线)
- 线段树扫描线upcoj2540
- 线段树之扫描线
- 大话数据结构读书笔记 3---串
- 程序是如何执行的(三)函数调用
- gem install安装报SSL证书错误的解决办法
- 逆序建立链表
- 算法导论第六章-堆排序c++
- 线段树扫描线hdu1828Picture
- 傅里叶变换的简单理解
- 程序员之工具杂烩
- C++
- 机器学习基础(二):决策树
- MAC OS X环境下Sublime text保存失败
- HDU 1394 Minimum Inversion Number
- 王爽汇编第二版第7章实验6
- Hibernate对象的三种状态