线段树[扫描线]
来源:互联网 发布:vim python 环境 编辑:程序博客网 时间:2024/04/29 06:12
hdu1542 Atlantis POJ 1151(C++才能过, G++WA到死)求矩形面积并
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=1000+123;//n=100struct Segm{ int ymin, ymax;//线段覆盖的区间,当然是离散后的坐标区间 /// 这里保存的是每个值i表示的是i-1到i代表的点之间的距离,因此ymin要+1; double x;//纪录当前线段在x轴的位置 int s;// 记录当前线段的进出 1 -1 bool operator < (const Segm & a) const { return x<a.x; }}seg[maxn];double T[maxn];//实际覆盖的区域int cover[maxn];// 记录被覆盖的次数double len[maxn];//离散后 线段树节点表示的实际长度int n, M, h;struct Map{ double y;//对y离散 int ind; bool operator < (const Map & a) const { return y<a.y; }}map[maxn];int bit(int x)/// get highest 1 in bit-number{ if(x==0)return 0; int n=31; if((x>>16)==0){n-=16; x<<=16;} if((x>>24)==0){n-=8; x<<=8;} if((x>>28)==0){n-=4; x<<=4;} if((x>>30)==0){n-=2; x<<=2;} return n-(x>>31);}void init(){ int cnt=0; for (int i=0; i<n; ++i) { scanf("%lf%lf%lf%lf", &seg[i<<1].x, &map[i<<1].y, &seg[i<<1|1].x, &map[i<<1|1].y); map[i<<1].ind=i<<1; map[i<<1|1].ind=i<<1|1; seg[i<<1].s=1; seg[i<<1|1].s=-1; } sort(map, map+n+n); for (int i=0; i<n+n; ++i) { if(i && map[i].y!=map[i-1].y) len[cnt++]=map[i].y-map[i-1].y;//这里在区间上直接去重 int num=map[i].ind>>1; if(map[i].ind&1) seg[num<<1].ymax=seg[num<<1|1].ymax=cnt-1; else seg[num<<1].ymin=seg[num<<1|1].ymin=cnt; } sort (seg, seg+n+n); h=bit(cnt); M=1<<h; memset (T, 0, sizeof(T)); memset (cover, 0, sizeof(cover)); for (int i=M+cnt; i>=M; --i) len[i]=len[i-M]; for (int i=M-1; i>0; --i) len[i]=len[i<<1]+len[i<<1|1];}void Updata(const int &x){ if(cover[x])T[x]=len[x]; else T[x]=(x>M? 0: T[x<<1]+T[x<<1|1]);}void IU(int l, int r, int v){///不需下传, 因为+1与-1的区间是对称的,有加必有减(不知这样理解对不) for (l+=M-1, r+=M+1; l^r^1; l>>=1, r>>=1, Updata(l), Updata(r)) { if(~l&1)cover[l^1]+=v, Updata(l^1); if( r&1)cover[r^1]+=v, Updata(r^1); } while (l>1) { l>>=1, r>>=1; if(l^r)Updata(r); Updata(l); }}int main (){ int I=1; while (scanf("%d", &n), n) { init(); n<<=1; double area=0.; double now=seg[0].x; for (int i=0; i<n; ++i) {//更新区间插入或删除线段, 记录上次的位置 Segm &a = seg[i]; area+=T[1]*(a.x-now);//第一为0 IU(a.ymin, a.ymax, a.s); now=a.x; } printf("Test case #%d\nTotal explored area: %.2lf\n\n", I++, area); } return 0;}
hdu 1828 矩形周长
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define abs(a) ((a)>0?(a):(-(a)))const int maxn=40000+123;//n=100struct Segm{ int ymin, ymax;//线段覆盖的区间,当然是离散后的坐标区间 /// 这里保存的是每个值i表示的是i-1到i代表的点之间的距离,因此ymin要+1; int x;//纪录当前线段在x轴的位置 int s;// 记录当前线段的进出 1 -1 bool operator < (const Segm & a) const { return x<a.x; }}seg[maxn];int T[maxn];//实际覆盖的区域int cover[maxn];// 记录被覆盖的次数int len[maxn];//离散后 线段树节点表示的实际长度int point[maxn];bool lc[maxn], rc[maxn];int n, M, h;struct Map{ int y;//对y离散 int ind; bool operator < (const Map & a) const { return y<a.y; }}map[maxn];int bit(int x)// get highest 1 in bit-number{ if(x==0)return 0; int n=31; if((x>>16)==0){n-=16; x<<=16;} if((x>>24)==0){n-=8; x<<=8;} if((x>>28)==0){n-=4; x<<=4;} if((x>>30)==0){n-=2; x<<=2;} return n-(x>>31);}void init(){ int cnt=0; for (int i=0; i<n; ++i) { scanf("%d%d%d%d", &seg[i<<1].x, &map[i<<1].y, &seg[i<<1|1].x, &map[i<<1|1].y); map[i<<1].ind=i<<1; map[i<<1|1].ind=i<<1|1; seg[i<<1].s=1; seg[i<<1|1].s=-1; } sort(map, map+n+n); for (int i=0; i<n+n; ++i) { if(i && map[i].y!=map[i-1].y) len[cnt++]=map[i].y-map[i-1].y;//这里在区间上直接去重 int num=map[i].ind>>1; if(map[i].ind&1) seg[num<<1].ymax=seg[num<<1|1].ymax=cnt-1; else seg[num<<1].ymin=seg[num<<1|1].ymin=cnt; } sort (seg, seg+n+n); h=bit(cnt); M=1<<h; memset (T, 0, sizeof(T)); memset (cover, 0, sizeof(cover)); memset (point, 0, sizeof(point)); memset (lc , 0, sizeof(lc)); memset (rc, 0, sizeof(rc)); for (int i=M+cnt; i>=M; --i) len[i]=len[i-M]; for (int i=M-1; i>0; --i) len[i]=len[i<<1]+len[i<<1|1];}void Updata(const int &x){ if(cover[x]) { T[x]=len[x]; lc[x]=1; rc[x]=1; point[x]=2; } else { lc[x]=(x>=M? 0: lc[x<<1]); rc[x]=(x>=M? 0: rc[x<<1|1]); point[x]=(x>=M? 0: point[x<<1]+point[x<<1|1]); if(rc[x<<1] && lc[x<<1|1])point[x]-=2; T[x]=(x>=M? 0: T[x<<1]+T[x<<1|1]); }}void IU(int l, int r, int v)/// 下传反而会错的, 改变了区间(秦牛说的){///不需下传, 因为+1与-1的区间是对称的,有加必有减(不知这样理解对不) for (l+=M-1, r+=M+1; l^r^1; l>>=1, r>>=1, Updata(l), Updata(r)) { if(~l&1)cover[l^1]+=v, Updata(l^1); if( r&1)cover[r^1]+=v, Updata(r^1); } while (l>1) { l>>=1, r>>=1; if(l^r)Updata(r); Updata(l); }}int main (){ int I=1; while (~scanf("%d", &n)) { init(); n<<=1; int per=0; int nowx=seg[0].x; int nowy=0; for (int i=0; i<n; ++i) {//更新区间插入或删除线段, 记录上次的位置 Segm &a = seg[i]; per+=point[1]*(a.x-nowx); //printf("===%d %lf\n", point[1], a.x-nowx); IU(a.ymin, a.ymax, a.s); per+=(abs(T[1]-nowy));//第一为0 //printf("%lf %lf\n", abs(T[1]-nowy), per); nowx=a.x; nowy=T[1]; } printf("%d\n", per); } return 0;}
- 线段树[扫描线]
- 线段树+扫描线
- 线段树 扫描线
- 线段树扫描线
- 线段树-扫描线
- hdu4007 线段树扫描线
- poj2482 线段树扫描线
- poj2464 线段树扫描线
- ural1707 线段树扫描线
- hdu4419 线段树扫描线
- hdu1828线段树+扫描线
- POJ1177+线段树+扫描线
- POJ1151+线段树+扫描线
- HDU3255(线段树+扫描线)
- 线段树扫描线upcoj2540
- 线段树之扫描线
- 线段树扫描线hdu4052
- 线段树扫描线uva11983
- Android ListView下拉刷新
- C语言非常用关键字解析
- 解决error:could not open(此处为安装路径如e:...) ...jvm.cfg
- C++实现插入排序
- 0-1背包问题(C++ && 详解)DP
- 线段树[扫描线]
- 头文件函数
- 对IT服务的一些思考(Some Thoughts on IT services)
- Linux设备驱动程序笔记1—USB设备基础
- Linux设备驱动程序笔记2—Urbs
- Android Activity的title设置
- Qualification Round Africa 2010 Problem B. Reverse Words
- Linux设备驱动程序笔记3—编写一个实际的USB驱动
- Android Google Map实例 - 添加GPS位置标注(Android mapview)