题目大意:给你n个点,m个操作,每个操作有两个参数k,a把所有满足y>k/(x^a)的点删掉,当然每个点只能被删一次,要求输出每个点时被哪个操作删的,如果最后仍没被删就-1
,保证所有的数都是正数 x,y,k,a都是实数,不超过10^6
这题因为是y>k/(x^a)比较蛋疼,所以把其化成alnx+lny>lnk,然后就可以整体二分了,每次判读左一半的操作能否将每个点删掉,
一个点被删掉,就是存在一个kj,aj使得alnx+lny>lnk,也就是求半平面并,看点是否在其内,但是半平面并不会写,那就求补集的半平面交,在看点是否在其外就OK了
写的比较丑
#include<cmath>
#include<cstdio>
#include<vector>
#include<cassert>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100011,maxm=100011;
const double inf=1e8;
const double eps=1e-10;
struct Tp{
<span style="white-space:pre"> </span>double x,y; int ans;
<span style="white-space:pre"> </span>void read(){scanf("%lf%lf",&x,&y); x=log2(x); y=log2(y);}
}p[maxn],*wp[maxn];
struct Tq{
<span style="white-space:pre"> </span>double k,a;
<span style="white-space:pre"> </span>void read(){scanf("%lf%lf",&k,&a); k=log2(k);}
}q[maxm];
struct point{
<span style="white-space:pre"> </span>double x,y;
<span style="white-space:pre"> </span>void watch(){printf("(%.5f,%.5f) ",x,y);}
};
point operator +(const point &a,const point &b){return (point){a.x+b.x,a.y+b.y};}
point operator -(const point &a,const point &b){return (point){a.x-b.x,a.y-b.y};}
point operator *(const point &a,const double &k){return (point){a.x*k,a.y*k};}
double operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;}
struct line{
<span style="white-space:pre"> </span>point p,vec; double k;
<span style="white-space:pre"> </span>void getk(){k=atan2(vec.y,vec.x);}
<span style="white-space:pre"> </span>bool check(const point &x){ // 在上也算
<span style="white-space:pre"> </span>return (vec*(x-p))>=0;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>bool check_(const point &x){ // 在上不算
<span style="white-space:pre"> </span>return (vec*(x-p))>0;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>bool operator <(const line &s)const{return k<s.k || k==s.k && vec*(s.p-p)<=0;}
};
point getpoint(const line &a,const line &b){
<span style="white-space:pre"> </span>double k=(b.vec*(a.p-b.p))/(a.vec*b.vec);
<span style="white-space:pre"> </span>return a.p+a.vec*k;
}
inline int sgn(double x){if (x<-eps) return -1; return x>eps;}
bool check(const point &a,const point &b,const point &c,const point &x){
<span style="white-space:pre"> </span>int s=sgn((a-x)*(b-x)); return s==sgn((b-x)*(c-x)) && s==sgn((c-x)*(a-x));
}
int n,m;
void init(){
<span style="white-space:pre"> </span>scanf("%d%d",&n,&m);
<span style="white-space:pre"> </span>for (int i=1;i<=n;++i) p[i].read(),wp[i]=p+i,p[i].ans=-1;
<span style="white-space:pre"> </span>for (int i=1;i<=m;++i) q[i].read();
}
void half_plane_intersection(line seg[],int n,point p[],int &t,int &w){
<span style="white-space:pre"> </span>for (int i=1;i<=n;++i) seg[i].getk(); sort(seg+1,seg+n+1);
<span style="white-space:pre"> </span>t=1,w=0; static line q[maxm];
<span style="white-space:pre"> </span>for (int i=1;i<=n;++i){
<span style="white-space:pre"> </span>while (t<w && !seg[i].check(p[w-1])) --w;
<span style="white-space:pre"> </span>while (t<w && !seg[i].check(p[t])) ++t;
<span style="white-space:pre"> </span>if (w<t || fabs(q[w].k-seg[i].k)>eps){
<span style="white-space:pre"> </span>q[++w]=seg[i]; if (w>t) p[w-1]=getpoint(q[w-1],q[w]);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>while (t<w && !q[t].check(p[w-1])) --w;
<span style="white-space:pre"> </span>if (t+1>=w) return;
<span style="white-space:pre"> </span>p[w]=getpoint(q[t],q[w]);
}
void getok(int lp,int rp,int l,int r,bool ok[]){ // lp,rp是点的区间,l,r是删除区间
<span style="white-space:pre"> </span>// 先用删除区间做半平面交,然后用点去看在不在其中,不在就Ok了
<span style="white-space:pre"> </span>// y<=k-ax
<span style="white-space:pre"> </span>int n=0,t,w; static line seg[maxm];
<span style="white-space:pre"> </span>for (int i=l;i<=r;++i){
<span style="white-space:pre"> </span>seg[++n].p=(point){0,q[i].k},seg[n].vec=(point){-1,q[i].a};
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>seg[++n].p=(point){inf,inf},seg[n].vec=(point){-1,0};
<span style="white-space:pre"> </span>seg[++n].p=(point){-inf,inf},seg[n].vec=(point){0,-1};
<span style="white-space:pre"> </span>seg[++n].p=(point){-inf,-inf},seg[n].vec=(point){1,0};
<span style="white-space:pre"> </span>seg[++n].p=(point){inf,-inf},seg[n].vec=(point){0,1};
<span style="white-space:pre"> </span>static point p[maxm]; half_plane_intersection(seg,n,p,t,w); // 求出来的是逆时针
<span style="white-space:pre"> </span>if (t+1>=w){for (int i=lp;i<=rp;++i) ok[i]=1; return;}
<span style="white-space:pre"> </span>for (int i=lp;i<=rp;++i){
<span style="white-space:pre"> </span>int head=t+1,tail=w; point x; x.x=wp[i]->x; x.y=wp[i]->y;
<span style="white-space:pre"> </span>while (head<=tail){
<span style="white-space:pre"> </span>int mid=(head+tail)>>1;
<span style="white-space:pre"> </span>if ((p[mid]-p[t])*(x-p[t])>=0) head=mid+1;
<span style="white-space:pre"> </span>else tail=mid-1;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>int tmp=head-1;
<span style="white-space:pre"> </span>if (tmp<=t || tmp>=w) ok[i]=1;
<span style="white-space:pre"> </span>else ok[i]=!check(p[t],p[tmp],p[tmp+1],x);
<span style="white-space:pre"> </span>}
}
void solve(int lp,int rp,int l,int r){ // lp,rp是点的区间,l,r是删除区间
<span style="white-space:pre"> </span>if (lp>rp) return; static bool ok[maxn];
<span style="white-space:pre"> </span>if (l==r){
<span style="white-space:pre"> </span>getok(lp,rp,l,l,ok);
<span style="white-space:pre"> </span>for (int i=lp;i<=rp;++i) if (ok[i]) wp[i]->ans=l; return;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>int mid=(l+r)>>1; getok(lp,rp,l,mid,ok);
<span style="white-space:pre"> </span>static Tp *tmp[maxn]; int cnt=lp-1,res;
<span style="white-space:pre"> </span>for (int i=lp;i<=rp;++i) if (ok[i]) tmp[++cnt]=wp[i]; res=cnt;
<span style="white-space:pre"> </span>for (int i=lp;i<=rp;++i) if (!ok[i]) tmp[++cnt]=wp[i];
<span style="white-space:pre"> </span>for (int i=lp;i<=rp;++i) wp[i]=tmp[i];
<span style="white-space:pre"> </span>solve(lp,res,l,mid); solve(res+1,rp,mid+1,r);
}
void work(){
<span style="white-space:pre"> </span>solve(1,n,1,m); for (int i=1;i<=n;++i) printf("%d\n",p[i].ans);
}
int main(){
<span style="white-space:pre"> </span>init();
<span style="white-space:pre"> </span>work();
<span style="white-space:pre"> </span>return 0;
}