• LUOGU P4088 [USACO18FEB]Slingshot(线段树)


    传送门

    解题思路

      推了推式子发现是个二维数点,想了想似乎排序加线段树难写,就写了个树套树,结果写完看见空间才(128M)。。各种奇技淫巧卡空间还是(MLE)到天上。后来只好乖乖的写排序+线段树。做法就是把式子写出来,然后把绝对值分类讨论成四种情况,发现这就是二维数点,然后讨论每种情况排序算最小值。

    代码1(树套树 30pts)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    const int N=200005;
    const int M=N*20;
    
    inline int rd(){
    	int x=0,f=1; char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    
    int n,m,xx[N<<2],yy[N<<2],tt[N],cnt,u,tot,cpy[N<<2],rt,num;
    LL ans=1e18;
    
    struct Segment_Tree_in{
    	int rt[N<<2],ls[M],rs[M];
    	LL Min[M];
    	inline void init(){
    		memset(Min,0x3f,sizeof(Min));
    	}
    	void update(int &x,int l,int r,int pos,LL w){
    		if(!x) x=++tot; Min[x]=min(Min[x],w);
    		if(l==r) return; int mid=(l+r)>>1;
    		if(pos<=mid) update(ls[x],l,mid,pos,w);
    		else update(rs[x],mid+1,r,pos,w);
    	}
    	LL query(int x,int l,int r,int L,int R){
    		if(!x) return 1e18;
    		if(L<=l && r<=R) return Min[x];
    		int mid=(l+r)>>1; LL ret=1e18;
    		if(L<=mid) ret=min(ret,query(ls[x],l,mid,L,R));
    		if(mid<R) ret=min(ret,query(rs[x],mid+1,r,L,R));
    		return ret;
    	}
    }tree2[2];
    
    struct Segment_Tree_out{
    	int ls[N<<2],rs[N<<2];
    	void update(int &x,int l,int r,int i,int op){
    		if(!x) x=++num; 
    		tree2[0].update(tree2[0].rt[x],1,u,yy[i],1ll*cpy[xx[i]]*op+cpy[yy[i]]+tt[i]);
    		tree2[1].update(tree2[1].rt[x],1,u,yy[i],1ll*cpy[xx[i]]*op-cpy[yy[i]]+tt[i]);
    		if(l==r) return; int mid=(l+r)>>1;
    		if(xx[i]<=mid) update(ls[x],l,mid,i,op);
    		else update(rs[x],mid+1,r,i,op);
    	}
    	LL query(int x,int l,int r,int x1,int x2,int y1,int y2,int op){
    		if(!x) return 1e18;
    		if(x1<=l && r<=x2) return tree2[op].query(tree2[op].rt[x],1,u,y1,y2);
    		int mid=(l+r)>>1; LL ret=1e18;
    		if(x1<=mid) ret=min(ret,query(ls[x],l,mid,x1,x2,y1,y2,op));
    		if(mid<x2) ret=min(ret,query(rs[x],mid+1,r,x1,x2,y1,y2,op));
    		return ret;
    	}
    }tree1[2];
    
    //0+ 1-
    
    int main(){
    	tree2[0].init(); tree2[1].init();
    	n=rd(),m=rd(); int x,y,t,X,Y;
    	for(int i=1;i<=n;i++){
    		x=rd(),y=rd(),t=rd();
    		xx[i]=x; yy[i]=y; tt[i]=t;
    		cpy[++cnt]=x; cpy[++cnt]=y;
    	}
    	for(int i=1;i<=m;i++){
    		x=rd(),y=rd();
    		cpy[++cnt]=x; cpy[++cnt]=y;
    		xx[i+n]=x; yy[i+n]=y;
    	}
    	sort(cpy+1,cpy+1+cnt);
    	u=unique(cpy+1,cpy+1+cnt)-cpy-1;
    	for(int i=1;i<=n;i++){
    		xx[i]=lower_bound(cpy+1,cpy+1+u,xx[i])-cpy;
    		yy[i]=lower_bound(cpy+1,cpy+1+u,yy[i])-cpy;
    		tree1[0].update(rt,1,u,i,1);
    		tree1[1].update(rt,1,u,i,-1);
    	}
    	for(int i=1;i<=m;i++){
    		x=lower_bound(cpy+1,cpy+1+u,xx[i+n])-cpy;
    		y=lower_bound(cpy+1,cpy+1+u,yy[i+n])-cpy; 
    		ans=abs(cpy[x]-cpy[y]); 
    		ans=min(ans,tree1[0].query(1,1,u,x+1,u,y+1,u,0)-cpy[x]-cpy[y]);
    		ans=min(ans,tree1[0].query(1,1,u,x+1,u,1,y,1)-cpy[x]+cpy[y]);
    		ans=min(ans,tree1[1].query(1,1,u,1,x,y+1,u,0)+cpy[x]-cpy[y]);
    		ans=min(ans,tree1[1].query(1,1,u,1,x,1,y,1)+cpy[x]+cpy[y]);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    代码2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    const int N=400005;
    
    inline int rd(){
    	int x=0,f=1; char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    
    int n,m,xx[N<<2],yy[N<<2],tt[N],cnt,u,cpy[N<<2];
    LL ans[N];
    
    struct Segment_Tree{
    	LL Min[N<<2];
    	inline void init(){
    		memset(Min,0x3f,sizeof(Min));
    	}
    	void update(int x,int l,int r,int pos,LL w){
    		Min[x]=min(Min[x],w);
    		if(l==r) return; int mid=(l+r)>>1;
    		if(pos<=mid) update(x<<1,l,mid,pos,w);
    		else update(x<<1|1,mid+1,r,pos,w);
    	}
    	LL query(int x,int l,int r,int L,int R){
    		if(L<=l && r<=R) return Min[x];
    		int mid=(l+r)>>1; LL ret=1e18;
    		if(L<=mid) ret=min(ret,query(x<<1,l,mid,L,R));
    		if(mid<R) ret=min(ret,query(x<<1|1,mid+1,r,L,R));
    		return ret;
    	}
    }tree;
    
    struct Node{
    	int x,y,t,op,id;
    	Node(int _x=0,int _y=0,int _t=0,int _op=0,int _id=0){
    		x=_x; y=_y; t=_t; op=_op; id=_id;
    	}
    }node[N];
    
    inline bool cmp1(Node A,Node B){
    	return (A.x==B.x)?A.y<B.y:A.x<B.x;
    }
    inline bool cmp2(Node A,Node B){
    	return (A.x==B.x)?A.y>B.y:A.x<B.x;
    } 
    inline bool cmp3(Node A,Node B){
    	return (A.x==B.x)?A.y<B.y:A.x>B.x;
    }
    inline bool cmp4(Node A,Node B){
    	return (A.x==B.x)?A.y>B.y:A.x>B.x;
    }
    
    int main(){
    	n=rd(),m=rd(); int x,y,t,pos;
    	for(int i=1;i<=n;i++){
    		x=rd(),y=rd(),t=rd();
    		xx[i]=x; yy[i]=y; tt[i]=t;
    		cpy[++cnt]=x; cpy[++cnt]=y;
    	}
    	for(int i=1;i<=m;i++){
    		x=rd(),y=rd(); ans[i]=abs(x-y);
    		cpy[++cnt]=x; cpy[++cnt]=y;
    		xx[i+n]=x; yy[i+n]=y;
    	}
    	sort(cpy+1,cpy+1+cnt);
    	u=unique(cpy+1,cpy+1+cnt)-cpy-1;
    	for(int i=1;i<=n;i++) {
    		xx[i]=lower_bound(cpy+1,cpy+1+u,xx[i])-cpy;
    		yy[i]=lower_bound(cpy+1,cpy+1+u,yy[i])-cpy;
    		node[i]=Node(xx[i],yy[i],tt[i],0,0);
    	}
    	for(int i=1;i<=m;i++){
    		x=lower_bound(cpy+1,cpy+1+u,xx[i+n])-cpy;
    		y=lower_bound(cpy+1,cpy+1+u,yy[i+n])-cpy; 
    		node[i+n]=Node(x,y,0,1,i);
    	}
    	tree.init();
    	sort(node+1,node+1+n+m,cmp1);
    	for(int i=1;i<=n+m;i++){
    		x=node[i].x,y=node[i].y;
    		if(!node[i].op) tree.update(1,1,u,y,-cpy[x]-cpy[y]+node[i].t);
    		else ans[node[i].id]=min(ans[node[i].id],tree.query(1,1,u,1,y)+cpy[x]+cpy[y]);
    	}
    	tree.init();
    	sort(node+1,node+1+n+m,cmp2);
    	for(int i=1;i<=n+m;i++){
    		x=node[i].x,y=node[i].y;
    		if(!node[i].op) tree.update(1,1,u,y,-cpy[x]+cpy[y]+node[i].t);
    		else ans[node[i].id]=min(ans[node[i].id],tree.query(1,1,u,y+1,u)+cpy[x]-cpy[y]);
    	}
    	tree.init();
    	sort(node+1,node+1+n+m,cmp3);
    	for(int i=1;i<=n+m;i++){
    		x=node[i].x,y=node[i].y;
    		if(!node[i].op) tree.update(1,1,u,y,cpy[x]-cpy[y]+node[i].t);
    		else ans[node[i].id]=min(ans[node[i].id],tree.query(1,1,u,1,y)-cpy[x]+cpy[y]);
    	}
    	tree.init();
    	sort(node+1,node+1+n+m,cmp4);
    	for(int i=1;i<=n+m;i++){
    		x=node[i].x,y=node[i].y;
    		if(!node[i].op) tree.update(1,1,u,y,cpy[x]+cpy[y]+node[i].t);
    		else ans[node[i].id]=min(ans[node[i].id],tree.query(1,1,u,y+1,u)-cpy[x]-cpy[y]);
    	}
    	for(int i=1;i<=m;i++) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    centos7 安装 nginx
    centos 关闭防火墙
    springcloud + nacos + mybatis ,增加seata分布式事务
    docker 运行 seata-server 配置nacos
    分布式事务4种方式,通俗易解篇
    主键字段报错doesn't have a default value (mybatis)
    模拟部署一个前后端分离的项目
    nginx配置接口转发路径
    前端部署后出现白板异常
    nodeJs的升降级(win10下)
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10429653.html
Copyright © 2020-2023  润新知