转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:给出n*n个格子,每个格子上有若干个单位立方体。从无穷远有一片光线,问最多能照到多少个立方体
http://codeforces.com/contest/243/problem/D
我们对于每个格子,通过向量求出某个区间,表示这个区间的发射的光线可以照射到立方体上。
至于 这个点通过向量怎么映射的怎么解决呢。
首先我们考虑一下区间[L,R]。我们考虑3个点(0,0)(vx,vy)(x,y)怎么表示(x,y)在向量垂直上的映射呢。
通过叉积,求出夹角就可以相对的表示“左右关系”。
利用点积表示"前后关系"
对于一个格子,我们考虑的不是一个点,求出4个点的叉积点积,取最小值为左端点,最大值为右端点,就得到一个区间为格子的映射,取点积的最小值(最前面的)表示前后关系。
将坐标离散化一下,线段树中保存的是当前区间的最低的阻挡高度。
也就是线段树中保存的是最小值,而我们用最大值去更新。
这题点非常多啊,10e6,卡爆了,勉强常数优化过去。
(艹这样的题解也能发?还是去这里吧http://blog.csdn.net/dslovemz/article/details/8203366
不错的题目,欢迎私聊,不过也有神做法,效率很高
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 100000005
#define M 200005
#define N 2100000
#define maxn 300005
#define eps 1e-10
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
//#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson step<<1
#define rson step<<1|1
#define MOD 1000000009
#define sqr(a) ((a)*(a))
#define Key_value ch[ch[root][1]][0]
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
vector<int>coor;
int n,vx,vy;
inline int min(int a,int b ){return a<b?a:b;}
inline int max(int a,int b ){return a>b?a:b;}
struct Cube
{
int l,r,h,d;
inline void Init(int x,int y,int _h)
{
h=_h;
vector<int>a,b;
for(int xx=x;xx<=x+1;xx++)
{
for(int yy=y;yy<=y+1;yy++)
{
a.pb(xx*vy-yy*vx);
b.pb(xx*vx+yy*vy);
}
}
l=*min_element(a.begin(),a.end())*2;
r=*max_element(a.begin(),a.end())*2;
d=*min_element(b.begin(),b.end());
coor.pb(l);coor.pb(r);
}
bool operator<(const Cube c)const
{
return d<c.d;
}
};
struct Node
{
int left,right;
int lazy,val;
}L[N<<2];
vector<Cube>cube;
map<int,int>mp;
void Push_Up(int step)
{
L[step].val=min(L[lson].val,L[rson].val);
}
void Push_Down(int step)
{
if(L[step].lazy)
{
L[lson].lazy=max(L[step].lazy,L[lson].lazy);
L[rson].lazy=max(L[step].lazy,L[rson].lazy);
L[lson].val=max(L[step].lazy,L[lson].val);
L[rson].val=max(L[step].lazy,L[rson].val);
L[step].lazy=0;
}
}
void Bulid(int step,int l,int r)
{
L[step].left=l;
L[step].right=r;
int m=(l+r)/2;
L[step].lazy=L[step].val=0;
if(l==r) return ;
Bulid(lson,l,m);
Bulid(rson,m+1,r);
}
inline void Update(int step,int l,int r,int c)
{
if(L[step].left==l&&L[step].right==r)
{
L[step].lazy=max(L[step].lazy,c);
L[step].val=max(L[step].val,c);
return ;
}
Push_Down(step);
int m=(L[step].left+L[step].right)>>1;
if(r<=m) Update(lson,l,r,c);
else if(l>m) Update(rson,l,r,c);
else
{
Update(lson,l,m,c);
Update(rson,m+1,r,c);
}
Push_Up(step);
}
inline int Query(int step,int l,int r)
{
if(L[step].left==l&&L[step].right==r)
{
return L[step].val;
}
Push_Down(step);
int m=(L[step].left+L[step].right)>>1;
if(r<=m) return Query(lson,l,r);
else if(l>m) return Query(rson,l,r);
else return min(Query(lson,l,m),Query(rson,m+1,r));
}
int main()
{
while(scanf("%d%d%d",&n,&vx,&vy)!=EOF)
{
cube.clear();
mp.clear();
int first=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
int h;
scanf("%d",&h);
if(!h){if(first) continue; first=1; }
Cube tmp;tmp.Init(i,j,h);
cube.pb(tmp);
}
}
sort(coor.begin(),coor.end());
unique(coor.begin(),coor.end());
sort(cube.begin(),cube.end());
n=coor.size();
Bulid(1,1,n);
LL ans=0;
for(int i=0;i<n;i++) mp[coor[i]]=i+1;
for(int i=0;i<cube.size();i++)
{
cube[i].l=mp[cube[i].l];
cube[i].r=mp[cube[i].r]-1;
// cout<<cube[i].l<<" "<<cube[i].r<<endl;
}
for(int i=0;i<cube.size();i++)
{
int ret=Query(1,cube[i].l,cube[i].r);
if(ret<cube[i].h)
{
ans+=cube[i].h-ret;
Update(1,cube[i].l,cube[i].r,cube[i].h);
}
}
printf("%I64d\n",ans);
}
return 0;
}