题意:
按图中所示的方式摆放正方形。输出那些正方形从上往下看得到的正方形。
题解:1:由于所有线段都成45/135度角的关系,将所有数据大sqrt(2)倍,便可以当做整数来处理。2:用线段树处理覆盖的时候,由于只能处理整点,下面的情况需要注意
即第3只有最左边的一点可以看到。但是第2却把该点标为2,这样一来得到的结果就是3看不到。为避免这种情况发生,可以将每一个正方形的左右两点都乘以2,然后右边的点再减去1.(类似于开区间闭区间的处理)
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
#define L(u) ((u)<<1)
#define R(u) ((u)<<1|1)
struct Square
{
int b, l, r, len, id, flag;
} s[500];
struct NODE
{
int l, r, flag;
} node[10000];
bool mark[500];
void build ( int u, int l, int r )
{
node[u].l = l;
node[u].r = r;
node[u].flag = 0;
if ( l == r ) return;
int mid = ( l + r ) >> 1;
build (L(u), l, mid );
build (R(u), mid+1, r );
}
void update ( int u, int l, int r, int f )
{
if ( node[u].l == l && node[u].r == r )
{
node[u].flag = f; return;
}
if ( node[u].flag != 0 )
{
node[L(u)].flag = node[u].flag;
node[R(u)].flag = node[u].flag;
node[u].flag = 0;
}
int mid = ( node[u].l + node[u].r ) >> 1;
if ( r <= mid )
update ( L(u), l, r, f );
else if ( l > mid )
update ( R(u), l, r, f );
else
{
update ( L(u), l, mid, f );
update ( R(u), mid+1, r, f );
}
}
void query ( int u )
{
if ( node[u].flag != 0 )
{
mark[node[u].flag] = true;
return;
}
if ( node[u].l == node[u].r ) return;
query(L(u)); query(R(u));
}
bool cmp ( const Square & a, const Square & b )
{
return a.len <= b.len;
}
int main()
{
int n;
while ( scanf("%d",&n) && n )
{
int i, j, tmp, t = 0;
for ( i = 1; i <= n; i++ )
{
scanf("%d",&s[i].len);
s[i].id = i; tmp = 0;
if ( i == 1 )
s[i].b = s[i].len;
else
{
for ( j = i - 1; j >= 1; j-- ) //枚举所有i前面的矩形,让第i个矩形与前面的某一个矩形紧凑的靠在一起
{
if ( s[i].len > s[j].len )
tmp = max(tmp, s[j].b+s[j].len*2);
else { tmp = max(tmp, s[j].b+s[i].len*2); break;}
}
if ( j < 1 && s[i].len >= tmp ) s[i].b = s[i].len;
else s[i].b = tmp;
}
s[i].l = ( s[i].b - s[i].len ) * 2; //注意!!!
s[i].r = ( s[i].b + s[i].len ) * 2 - 1; //!!!
t = max(s[i].r,t);
}
sort(s+1,s+1+n,cmp);
build ( 1, 0, t );
memset(mark,0,sizeof(mark));
for ( i = 1; i <= n; i++ )
update ( 1, s[i].l, s[i].r, s[i].id );
query ( 1 );
for ( i = 1; i <= n; i++ )
if ( mark[i] ) printf("%d ", i);
printf("\n");
}
return 0;
}