第一件要干的事就是把它给你的坐标用它给你的两个向量表示出来,事实上这件事就够令人发狂了…
所以开始解方程.
我们有
那么如果在变换后Q[i]能够照到Q[j],那么一定有
这样我们现在的问题就是要知道什么时候它会第一次亮.
那么考虑一下分治.
现在我们有一个时间区间[L,R],以及一个灯的区间[l,r].
然后取一半得到一个时间的mid,然后就可以知道哪些灯是现在就可以点亮的了,而哪些灯还要再过一会才可以点亮,那么这些灯我们对于它的K,我们把现在能够照到它的灯的数量减去,以后不予以计算.
这样的话,我们就可以把这些灯分成两份:在mid时间前可以被点完的,以及在mid时间前不能够被点完的.
然后继续递归去求解就行了.
#include
#include
#include
#include
#include
#define M 200005
#define LL long long
#define y1 saiff
using namespace std;
templatevoid Rd(T &res){
res=0;char p;int k=1;
while(p=getchar(),!(p>='0'&&p<='9')&&(p!='-'));
if(p=='-')k=-1,p=getchar();
do{
res=(res<<1)+(res<<3)+(p^48);
}while(p=getchar(),p>='0');
res*=k;
}
int n,x1,x2,y1,y2;
struct W{
LL x,y;
int id,K;
bool operator <(const W &a)const{
if(x!=a.x)return xreturn yint psz=0;
void dop(int &x,int &y){
int tmp=max(abs(x),abs(y));
int pl=(2000000000LL+tmp+2-1)/tmp;
x*=pl,y*=pl;x++;
}
struct Bit{
int Tree[M];
void Add(int x,int v){
while(xint Sum(int x){
int re=0;
while(x){
re+=Tree[x];
x-=x&(-x);
}
return re;
}
}T;
struct IHUS{
int ans[M];
void tot_solve(int L,int R,int l,int r){
if(l>r)return;
if(L==R){
for(int j=l;j<=r;j++)ans[Q[j].id]=L;
return;
}
int mid=(L+R)>>1,Mid=l;
sort(Q+l,Q+r+1);
for(int i=l;i<=r;i++){
if(Q[i].id<=mid){
T.Add(Q[i].y,1);
swap(Q[i],Q[Mid++]);
continue;
}else {
int tmp=T.Sum(Q[i].y);
if(tmp>=Q[i].K){
T.Add(Q[i].y,1);
swap(Q[i],Q[Mid++]);
}else Q[i].K-=tmp;
}
}
for(int i=l;i1);
tot_solve(L,mid,l,Mid-1);
tot_solve(mid+1,R,Mid,r);
}
void solve(){
for(int i=1;i<=n;i++){
LL nx=(1LL*x2*Q[i].y-1LL*Q[i].x*y2),ny=(1LL*Q[i].x*y1-1LL*x1*Q[i].y);
Q[i].x=nx,Q[i].y=ny;
}
psz=0;
for(int i=1;i<=n;i++)pl[psz++]=Q[i].x;
sort(pl,pl+psz);psz=unique(pl,pl+psz)-pl;
for(int i=1;i<=n;i++)Q[i].x=lower_bound(pl,pl+psz,Q[i].x)-pl+1;
psz=0;
for(int i=1;i<=n;i++)pl[psz++]=Q[i].y;
sort(pl,pl+psz);psz=unique(pl,pl+psz)-pl;
for(int i=1;i<=n;i++)Q[i].y=lower_bound(pl,pl+psz,Q[i].y)-pl+1;
sort(Q+1,Q+n+1);
tot_solve(1,n,1,n);
for(int i=1,f=0;i<=n;i++){
if(f)putchar(' ');f=true;
printf("%d",ans[i]);
}
putchar('\n');
}
}Nom;
int main(){
// freopen("lam.in","r",stdin);
// freopen("lam.out","w",stdout);
Rd(n),Rd(x1),Rd(y1),Rd(x2),Rd(y2);
for(int i=1;i<=n;i++)Rd(Q[i].x),Rd(Q[i].y);
for(int i=1;i<=n;i++)Rd(Q[i].K),Q[i].id=i;
if(1LL*x1*y2==1LL*x2*y1)dop(x1,y1);
if(1LL*x2*y1-1LL*x1*y2<0)swap(x1,x2),swap(y1,y2);
Nom.solve();
return 0;
}