• Jzoj5234 外星人的路径


    有一个外星人控制了你的大脑。一开始你处于原点(0,0)。外星人有一个由(R,U,D,L)组成的长度为M 的操作序列,分别代表(右,上,下,左)。

    平面上有N 个关键点,每当外星人给出一个操作,你需要在这个方向上找到最近的一个关键点,并走到那个点上。保证输入数据合法。

    100%的数据,N,M≤100000,xi,yi≤200000。

    这样,我们搞2个权值线段树,一个存横坐标一个存纵坐标,每次查询当前坐标的前继或者后续即可

    复杂度O(mlgn)

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define M 200010
    #define ls s[x].l
    #define rs s[x].r
    using namespace std;
    struct nod{ int l,r,s; };
    struct Tree{
    	nod s[3000000];
    	int rt[M<<1],c;
    	Tree(){ 
    		c=0; s[0]=(nod){0,0,0};
    		memset(rt,0,sizeof rt);
    	}
    	inline int newnode(){ return ++c; }
    	void ps(int x){ s[x].s=s[ls].s+s[rs].s; }
    	void insert(int l,int r,int& x,int p){
    		if(!x) x=newnode();
    		if(l==r){ s[x].s=1; return; }
    		int m=l+r>>1;
    		if(p<=m) insert(l,m,ls,p);
    		  else insert(m+1,r,rs,p);
    		ps(x);
    	}
    	int getmax(int l,int r,int x){
    		for(int m;l<r;){
    			m=l+r>>1;
    			if(s[rs].s) { l=m+1; x=rs; }
    			else { r=m; x=ls; }
    		}
    		return l;
    	}
    	int getmin(int l,int r,int x){
    		for(int m;l<r;){
    			m=l+r>>1;
    			if(s[ls].s) { r=m; x=ls; }
    			else { l=m+1; x=rs; }
    		}
    		return l;
    	}
    	int getpre(int l,int r,int x,int p){
    		if(l==r) return p;
    		int m=l+r>>1,v;
    		if(p<=m) return getpre(l,m,ls,p);
    		else v=getpre(m+1,r,rs,p);
    		if(v!=p||!s[ls].s) return v;
    		else return getmax(l,m,ls);
    	}
    	int getsuc(int l,int r,int x,int p){
    		if(l==r) return p;
    		int m=l+r>>1,v;
    		if(p>m) return getsuc(m+1,r,rs,p);
    		else v=getsuc(l,m,ls,p);
    		if(v!=p||!s[rs].s) return v;
    		else return getmin(m+1,r,rs);
    	}
    	void insert(int x,int y){ insert(1,M<<1,rt[x],y); }
    	int pre(int x,int y){ return getpre(1,M<<1,rt[x],y); }
    	int suc(int x,int y){ return getsuc(1,M<<1,rt[x],y); }
    } rot,lin;
    int n,m,x,y; char s[100010];
    int main(){
    	freopen("tratincice.in","r",stdin);
    	freopen("tratincice.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	rot.insert(M,M);
    	lin.insert(M,M);
    	for(int i=0;i<n;++i){
    		scanf("%d%d",&x,&y);
    		x+=M; y+=M;
    		rot.insert(x,y);
    		lin.insert(y,x);
    	}
    	x=y=M; scanf("%s",s);
    	for(int i=0;i<m;++i){
    		if(s[i]=='U') y=rot.suc(x,y);
    		if(s[i]=='D') y=rot.pre(x,y);
    		if(s[i]=='L') x=lin.pre(y,x);
    		if(s[i]=='R') x=lin.suc(y,x);
    	}
    	printf("%d %d
    ",x-M,y-M);
    }

  • 相关阅读:
    SVN 使用教程
    MVC图片上传压缩
    MVC 上传下载压缩
    C# WinForm生成二维码,一维码,条形码 操作
    C#MVC生成二维码
    ajax post方式提交到.net core api
    .net core多文件上传 日志记录
    C# .net Core 文件上传
    C#.netmvc单文件上传 ajax上传文件
    详细的sql语句
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477205.html
Copyright © 2020-2023  润新知