[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\n",ans[i]);
    return;
}

int main()
{
    init();
    solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AH2002/p/10208475.html
今日推荐