可以将给出的直线视作向量,那么当这两个向量不共线时(共线时情况类似),建立出以这两个向量为基底的坐标系,将坐标取反后,每盏灯(x,y)亮了后,能照亮的区域是(<=x,<=y),然后直接暴力弄这个东西就行了
因为不会写树套树qwq,我写了kd-tree,卡了半天卡过去了qwq
为了减小常数写了指针和一些奇奇怪怪的东西,代码可能不会很友好
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void read(int &x)
{
char c; int sig=1;
while(!((c=getchar())>='0'&&c<='9')) if(c=='-') sig=-1;
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
x*=sig;
}
inline void up(int &x,const int &y){if(x<y)x=y;}
inline void down(int &x,const int &y){if(x>y)x=y;}
const int maxn = 210000;
const int maxd = 2;
const long double eps = 1e-10;
inline bool low(const long double x,const long double y){return x-y<-eps;}
inline bool same(const long double x,const long double y){return fabs(x-y)<eps;}
int ct1,ct2,ct3,ct4,ct5,ct6;
bool flag;
int n;
int X1,Y1,X2,Y2;
struct node{long double x,y;int i;}a[maxn];
inline bool cmpx(const node x,const node y){return low(x.x,y.x);}
inline bool cmpy(const node x,const node y){return low(x.y,y.y);}
struct kd_tree{int i,fa,u[maxd],d[maxd],p[maxd],ki,mn,fl;kd_tree *lc,*rc;}kd[maxn]; int root;
int To[maxn];
void pushdown(kd_tree *x)
{
++ct1;
int fl=x->fl; x->fl=0;
kd_tree *lc=x->lc,*rc=x->rc;
if(lc!=NULL) lc->mn-=fl,lc->ki-=fl,lc->fl+=fl;
if(rc!=NULL) rc->mn-=fl,rc->ki-=fl,rc->fl+=fl;
}
void pushup(kd_tree *x)
{
++ct2;
x->mn=x->ki;
if(x->lc) down(x->mn,x->lc->mn);
if(x->rc) down(x->mn,x->rc->mn);
}
int cmpd;
inline bool cmp(const kd_tree &x,const kd_tree &y){return x.p[cmpd]<y.p[cmpd];}
int build(const int l,const int r,const int nowd)
{
int x=l+r>>1;
cmpd=nowd; std::nth_element(kd+l,kd+x,kd+r+1,cmp);
for(int i=0;i<maxd;i++) kd[x].u[i]=kd[x].d[i]=kd[x].p[i];
if(l!=x)
{
int lc=build(l,x-1,!nowd); kd[x].lc=&kd[lc]; kd[lc].fa=x;
for(int i=0;i<maxd;i++) down(kd[x].d[i],kd[lc].d[i]),up(kd[x].u[i],kd[lc].u[i]);
}
if(x!=r)
{
int rc=build(x+1,r,!nowd); kd[x].rc=&kd[rc]; kd[rc].fa=x;
for(int i=0;i<maxd;i++) down(kd[x].d[i],kd[rc].d[i]),up(kd[x].u[i],kd[rc].u[i]);
}
return pushup(&kd[x]),x;
}
int ans[maxn],nowi,oth;
int pos[maxd];
queue<int>q;
void clear(kd_tree *x)
{
++ct3;
if(x->fl) pushdown(x);
kd_tree *lc=x->lc,*rc=x->rc;
if(lc!=NULL&&lc->mn==0) clear(lc);
if(rc!=NULL&&rc->mn==0) clear(rc);
if(x->ki==0) ans[x->i]=nowi,x->ki=2*n+2,q.push(To[x->i]);
pushup(x);
}
void upd1(kd_tree *x)
{
++ct4;
if(x->mn>oth||pos[0]<x->d[0]||x->u[0]<pos[0]||pos[1]<x->d[1]) return;
if(x->d[0]==pos[0]&&x->u[0]==pos[0]&&x->u[1]<=pos[1])
{
x->fl++,x->ki--,x->mn--;
if(x->mn==0) clear(x);
return;
}
if(x->p[0]==pos[0]&&x->p[1]<=pos[1])
{
x->ki--;
if(!x->ki) ans[x->i]=nowi,x->ki=2*n+2,q.push(To[x->i]);
}
if(x->fl) pushdown(x);
if(x->lc) upd1(x->lc);
if(x->rc) upd1(x->rc);
pushup(x);
}
void upd2(kd_tree *x)
{
++ct5;
if(x->mn>oth||pos[0]<x->d[0]||pos[1]<x->d[1]) return;
if(x->u[0]<=pos[0]&&x->u[1]<=pos[1])
{
x->fl++,x->ki--,x->mn--;
if(x->mn==0) clear(x);
return;
}
if(x->p[0]<=pos[0]&&x->p[1]<=pos[1])
{
x->ki--;
if(!x->ki) ans[x->i]=nowi,x->ki=2*n+2,q.push(To[x->i]);
}
if(x->fl) pushdown(x);
if(x->lc) upd2(x->lc);
if(x->rc) upd2(x->rc);
pushup(x);
}
int t[maxn],tp;
int main()
{
read(n); read(X1),read(Y1); read(X2),read(Y2);
flag=(ll)X1*Y2==(ll)X2*Y1;
long double k=X1?(long double)Y1/X1:0.0,al=(long double)X1*Y2-(long double)X2*Y1;
for(int i=1;i<=n;i++)
{
int x,y; read(x); read(y);
long double kk;
if(flag) kk=!X1?x:(long double)y-k*x;
else kk=((long double)X1*y-(long double)x*Y1)/al;
a[i].x=-kk;
if(flag) kk=!X1?((long double)y/Y1):(long double)x/X1;
else kk=X1?((long double)x-kk*X2)/X1:((long double)y-kk*Y2)/Y1;
a[i].y=-kk;
a[i].i=i;
}
sort(a+1,a+n+1,cmpx);
for(int i=1,las=0;i<=n;i++)
{
if(!same(a[i].x,a[i-1].x))las++;
kd[a[i].i].p[0]=las;
}
sort(a+1,a+n+1,cmpy);
for(int i=1,las=0;i<=n;i++)
{
if(!same(a[i].y,a[i-1].y))las++;
kd[a[i].i].p[1]=las;
}
for(int i=1;i<=n;i++) read(kd[i].ki),kd[i].i=i;
root=build(1,n,0);
for(int i=1;i<=n;i++) To[kd[i].i]=i;
for(nowi=1,oth=n;nowi<=n;nowi++) if(!ans[nowi])
{
q.push(To[nowi]);
while(!q.empty())
{
const int x=q.front(); q.pop();
ans[kd[x].i]=nowi; kd[x].ki=2*n+2;
int tmp=x; tp=0; while(tmp) t[++tp]=tmp,tmp=kd[tmp].fa;
for(int j=tp;j>=1;j--) if(kd[t[j]].fl) pushdown(&kd[t[j]]);
for(int j=1;j<=tp;j++) pushup(&kd[t[j]]);
pos[0]=kd[x].p[0],pos[1]=kd[x].p[1];
if(flag) upd1(&kd[root]);
else upd2(&kd[root]);
oth--;
}
}
for(int i=1;i<n;i++) printf("%d ",ans[i]);
printf("%d\n",ans[n]);
//puts("");
//printf("%d %d %d %d %d\n",ct1,ct2,ct3,ct4,ct5);
return 0;
}