zoukankan      html  css  js  c++  java
  • [USACO18FEB]Slingshot

    题意可化为:

    在二维平面中有n个点,坐标为((x_i,y_i)),点权为(t_i)

    现有m个询问,每次给定点((x,y)),求(min{|x-x_i|+|y-y_i|+t_i,|y-x|})

    排序离散化后扫描线+分类讨论即可

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    using namespace std;
    
    const int MAXN=1<<18;
    const long long INF=1ll<<62;
    
    int n,m,mx;
    long long ans[MAXN];
    long long tree[2][MAXN<<1];
    struct rpg{
    	int x,y;
    	long long t;
    	int id,rey;
    }a[MAXN];
    
    inline int read()
    {
    	int x=0;char ch=getchar();
    	while(ch<'0'||'9'<ch) ch=getchar();
    	while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    	return x;
    }
    
    bool cmp1(rpg a,rpg b){return a.y<b.y;}
    bool cmp2(rpg a,rpg b){return a.x<b.x;}
    
    void init()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read(),a[i].t=read(),a[i].id=i;
    	for(int i=n+1;i<=n+m;++i) a[i].x=read(),a[i].y=read(),a[i].t=abs(a[i].y-a[i].x),a[i].id=i;
    	sort(a+1,a+n+m+1,cmp1);a[1].rey=1;
    	for(int i=2;i<=n+m;++i) a[i].rey=a[i].y==a[i-1].y?a[i-1].rey:a[i-1].rey+1;
    	mx=a[n+m].rey;
    	return;
    }
    
    void cchg(int k,int l,int r,int v,int id,bool kd)
    {
    	if(l==r){
    		if(!kd) tree[0][k]=min(tree[0][k],a[id].y-a[id].x+a[id].t),tree[1][k]=min(tree[1][k],a[id].t-a[id].x-a[id].y);
    		else tree[0][k]=min(tree[0][k],a[id].x+a[id].y+a[id].t),tree[1][k]=min(tree[1][k],a[id].x-a[id].y+a[id].t);
    		return;
    	}int i=k<<1,mid=l+r>>1;
    	if(v<=mid) cchg(i,l,mid,v,id,kd);
    	else cchg(i|1,mid+1,r,v,id,kd);
    	tree[0][k]=min(tree[0][i],tree[0][i|1]);
    	tree[1][k]=min(tree[1][i],tree[1][i|1]);
    	return;
    }
    
    long long cask(int k,int l,int r,int le,int ri,bool kd)
    {
    	if(le<=l&&r<=ri) return tree[kd][k];
    	int i=k<<1,mid=l+r>>1;long long mi=INF;
    	if(le<=mid) mi=min(mi,cask(i,l,mid,le,ri,kd));
    	if(mid<ri) mi=min(mi,cask(i|1,mid+1,r,le,ri,kd));
    	return mi;
    }
    
    void solve()
    {
    	sort(a+1,a+n+m+1,cmp2);
    	memset(tree,0x7f,sizeof(tree));
    	int ct1=1,ct2=0;
    	while(ct1<=n+m){
    		while(ct2+1<=n+m&&a[ct2+1].x==a[ct1].x){
    			++ct2;
    			if(a[ct2].id<=n) cchg(1,1,mx,a[ct2].rey,ct2,0);
    		}for(int i=ct1;i<=ct2;++i) if(a[i].id>n) a[i].t=min(a[i].t,min(cask(1,1,mx,1,a[i].rey,1)+a[i].y,cask(1,1,mx,a[i].rey,mx,0)-a[i].y)+a[i].x);
    		ct1=ct2+1;
    	}memset(tree,0x7f,sizeof(tree));
    	ct1=n+m,ct2=n+m+1;
    	while(ct1){
    		while(ct2-1&&a[ct2-1].x==a[ct1].x){
    			--ct2;
    			if(a[ct2].id<=n) cchg(1,1,mx,a[ct2].rey,ct2,1);
    		}for(int i=ct2;i<=ct1;++i) if(a[i].id>n) a[i].t=min(a[i].t,min(cask(1,1,mx,1,a[i].rey,1)+a[i].y,cask(1,1,mx,a[i].rey,mx,0)-a[i].y)-a[i].x);
    		ct1=ct2-1;
    	}for(int i=1;i<=n+m;++i) if(a[i].id>n) ans[a[i].id-n]=a[i].t;
    	for(int i=1;i<=m;++i) printf("%lld
    ",ans[i]);
    	return;
    }
    
    int main()
    {
    	init();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    ZOJ 3818 Pretty Poem
    HDU 4597 Play Game
    HDU 4497 GCD and LCM
    CSU 1335 高桥和低桥
    UVA 10791 Minimum Sum LCM
    CSU 1119 Collecting Coins
    CSU 1120 病毒
    UVA 12169 Disgruntled Judge
    HDU 1301 Jungle Roads
    POJ 1258 Agri-Net
  • 原文地址:https://www.cnblogs.com/AH2002/p/10208475.html
Copyright © 2011-2022 走看看