hdu1542 Atlantis POJ 1151(C++才能过, G++WA到死)求矩形面积并
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000+123;//n=100
struct 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=100
struct 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;
}