zoukankan      html  css  js  c++  java
  • LOJ#3085. 「GXOI / GZOI2019」特技飞行(KDtree+坐标系变换)

    题面

    传送门

    前置芝士

    请确定您会曼哈顿距离和切比雪夫距离之间的转换,以及(KDtree)对切比雪夫距离的操作

    题解

    我们发现(AB)(C)没有任何关系,所以关于(C)可以直接暴力数点

    关于暴力数点,这个曼哈顿距离很麻烦,先把它转成切比雪夫距离,然后就是一个(KDtree)的经典操作了

    容易发现交换操作的执行次数上界是(tot)(其中(tot)是交点个数),下界是(n-cnt)(其中(cnt)是原数组和飞过去之后的数组形成的一个置换,其中的轮换个数)

    证明的话……上界应该是很好证明的,以样例那张图为例,红色的是一号的路线,不难发现它的路线肯定是一个类似于上凸壳的东西,也就是说它飞到右边之后绝对只会在最上面。然后把这一条东西删除,二号飞机的路线肯定是剩下来的上凸壳,也会在最上面……最后肯定保持相对顺序不变

    下界的话,不同的置换之间是互不影响的,而设置换大小为(k),那么这里所需的最小交换次数为(k-1),所以总的次数为(sum (k-1)=n-cnt)

    关于为啥这里最小交换次数为(k-1)……因为它每一个交点都代表了一个逆序对,而交点里涵盖了所有的逆序对,所以交换逆序对的次数下界应该是(k-1)

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define inf 0x3f3f3f3f
    #define ll long long
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=5e5+5;const double eps=1e-8;
    inline double max(R double x,R double y){return x>y?x:y;}
    inline double fabs(R double x){return x<-eps?-x:x;}
    struct Point{
    	double p[2];
    	inline Point(){}
    	inline Point(R double xx,R double yy){p[0]=xx,p[1]=yy;}
    }poi[N];
    struct node;typedef node* ptr;
    struct node{
    	ptr lc,rc;double mn[2],mx[2];Point p;bool flag,ok;
    	inline node();
    	inline void init(R Point pp){
    		p=pp;
    		mn[0]=mx[0]=pp.p[0],mn[1]=mx[1]=pp.p[1];
    	}
    	inline double mndis(R int x,R int y){
    		return max(max(fabs(x-mn[0]),fabs(x-mx[0])),max(fabs(y-mn[1]),fabs(y-mx[1])));
    	}
    	inline double dis(R int x,R int y){return max(fabs(x-p.p[0]),fabs(y-p.p[1]));}
    }e[N],*rt;
    inline node::node(){lc=rc=e,mn[0]=mn[1]=inf,mx[0]=mx[1]=-inf;}
    void upd(ptr p,ptr s){
    	cmin(p->mn[0],s->mn[0]),cmin(p->mn[1],s->mn[1]);
    	cmax(p->mx[0],s->mx[0]),cmax(p->mx[1],s->mx[1]);
    }
    int WD,tot;
    inline bool operator <(const Point &a,const Point &b){return a.p[WD]<b.p[WD];}
    void build(ptr &p,int l,int r,int wd){
    	int mid=(l+r)>>1;p=(e+mid),WD=wd;
    	nth_element(poi+l,poi+mid,poi+r+1);
    	p->init(poi[mid]);
    	if(l<mid)build(p->lc,l,mid-1,wd^1),upd(p,p->lc);
    	if(mid<r)build(p->rc,mid+1,r,wd^1),upd(p,p->rc);
    }
    void update(ptr p,int x,int y,int d){
    	if(p==e||p->flag||x+d<p->mn[0]||x-d>p->mx[0]||y+d<p->mn[1]||y-d>p->mx[1])return;
    	if(p->mndis(x,y)-eps<=d)return p->flag=1,void();
    	if(!p->ok&&p->dis(x,y)-eps<=d)p->ok=1;
    	update(p->lc,x,y,d),update(p->rc,x,y,d);
    }
    int push(ptr p){
    	if(p->flag){
    		p->ok=1;
    		if(p->lc!=e)p->lc->flag=1,p->lc->ok=1;
    		if(p->rc!=e)p->rc->flag=1,p->rc->ok=1;
    	}
    	int res=p->ok;
    	if(p->lc!=e)res+=push(p->lc);
    	if(p->rc!=e)res+=push(p->rc);
    	return res;
    }
    int n,m,A,B,C,s,t,y[N],yy[N],id[N];double k[N],b[N],iv;
    ll ans1,ans2,ans;bool vis[N];
    set<pair<int,int> > si;
    set<pair<int,int> >::iterator it;
    inline bool cmp(const int &x,const int &y){return yy[x]<yy[y];}
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),A=read(),B=read(),C=read(),s=read(),t=read(),iv=1.0/(t-s);
    	fp(i,1,n)y[i]=read();fp(i,1,n)yy[i]=read();
    	fp(i,1,n)k[i]=(yy[i]-y[i])*iv,b[i]=y[i]-k[i]*s;
    	fd(i,n,1){
    		for(it=si.begin();it!=si.end()&&it->first<yy[i];++it){
    			R int j=it->second;
    			double tx=(b[j]-b[i])/(k[i]-k[j]);
    			double ty=k[i]*tx+b[i];
    			double x=tx+ty,y=tx-ty;
    			poi[++tot]=Point(x,y);
    		}
    		si.insert(make_pair(yy[i],i));
    	}
    	build(rt,1,tot,0);
    	m=read();
    	for(R int x,y,dx,dy,d;m;--m){
    		dx=read(),dy=read(),d=read(),
    		x=dx+dy,y=dx-dy;
    		update(rt,x,y,d);
    	}
    	ans=push(rt)*C,ans1=ans+tot*A;
    	fp(i,1,n)id[i]=i;
    	sort(id+1,id+1+n,cmp);
    	int res=0;
    	fp(i,1,n)if(!vis[i]){
    		++res;
    		for(R int j=i;!vis[j];j=id[j])vis[j]=1;
    	}
    	ans2=ans+(n-res)*A+(tot-n+res)*B;
    	if(ans1>ans2)swap(ans1,ans2);
    	printf("%lld %lld
    ",ans1,ans2);
    	return 0;
    }
    
  • 相关阅读:
    Net Core -- 配置Kestrel端口
    NET Core迁移
    NET Core 2.0 微服务跨平台实践
    NET Core 与 Vue.js 服务端渲染
    Varnish 实战
    Hitchhiker 是一款开源的 Restful Api 测试工具
    ABP框架用Dapper实现通过SQL访问数据库
    开源框架总体介绍
    Net Core API网关Ocelot
    Jquery autocomplete插件
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10720555.html
Copyright © 2011-2022 走看看