ZOJ 3724 Delivery(离线线段树)

来源:互联网 发布:网络借条平台 编辑:程序博客网 时间:2024/05/02 02:35

题意:N个点,对于每个点i,都有一条连向i+1的有向边,另外有M条其他的有向边,有Q个询问(U,V)求U到V的最短路。

当U<V的时候,很好处理查询下U到V范围内哪条边节省的时间多就可以了。U>V的处理方法很相似。分两种情况,分别离线处理一次就可以了。

//#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <algorithm>#include <queue>#include <set>#include <map>using namespace std;typedef long long LL;typedef pair<int,int> PII;#define INF (1LL<<60)#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=100005;LL A[N],sum[N],ans[N*2];struct OP{    int st,ed,w;    OP(){}    OP(int st,int ed,int w) :        st(st),ed(ed),w(w) {}};bool cmpST(const OP &A,const OP &B){    return A.st<B.st;}bool cmpED(const OP &A,const OP &B){    return A.ed<B.ed;}vector<OP> QA,QB;vector<OP> RA,RB;struct Segtree{    LL mx[N*4];    void PushUp(int ind)    {        mx[ind]=max(mx[LL(ind)],mx[RR(ind)]);    }    void build(int lft,int rht,int ind)    {        mx[ind]=-INF;        if(lft!=rht)        {            int mid=MID(lft,rht);            build(lft,mid,LL(ind));            build(mid+1,rht,RR(ind));        }    }    void updata(int pos,LL valu,int lft,int rht,int ind)    {        if(lft==rht) mx[ind]=max(mx[ind],valu);        else        {            int mid=MID(lft,rht);            if(pos<=mid) updata(pos,valu,lft,mid,LL(ind));            else updata(pos,valu,mid+1,rht,RR(ind));            PushUp(ind);        }    }    LL query(int st,int ed,int lft,int rht,int ind)    {        if(st<=lft&&rht<=ed) return mx[ind];        else        {            LL mx1=-INF,mx2=-INF;            int mid=MID(lft,rht);            if(st<=mid) mx1=query(st,ed,lft,mid,LL(ind));            if(ed> mid) mx2=query(st,ed,mid+1,rht,RR(ind));            return max(mx1,mx2);        }    }}seg;int main(){   // freopen("in.txt","r",stdin);    int n,m,Q;    while(scanf("%d%d",&n,&m)!=EOF)    {        QA.clear(); QB.clear();        RA.clear(); RB.clear();        int len1=0,len2=0;        sum[1]=0;        for(int i=2;i<=n;i++) scanf("%lld",&A[i]);        for(int i=2;i<=n;i++) sum[i]=A[i]+sum[i-1];        for(int i=0;i<m;i++)        {            int a,b,c; scanf("%d%d%d",&a,&b,&c);            if(a<b)            {                if(sum[b]-sum[a]<c) continue;                else RA.push_back(OP(a,b,(sum[b]-sum[a])-c));            }            else            {                LL tmp=sum[b]+(sum[n]-sum[a]);                RB.push_back(OP(b,a,tmp-c));            }        }        scanf("%d",&Q);        for(int i=0;i<Q;i++)        {            int a,b; scanf("%d%d",&a,&b);            if(a<b) QA.push_back(OP(a,b,i));            else if(a>b) QB.push_back(OP(b,a,i));            else ans[i]=0;        }        seg.build(1,n,1);        sort(QA.begin(),QA.end(),cmpED);        sort(RA.begin(),RA.end(),cmpED);        len1=(int)QA.size();        len2=(int)RA.size();        int ind=0;        for(int i=0;i<len1;i++)        {            while(ind<len2&&RA[ind].ed<=QA[i].ed)            {                seg.updata(RA[ind].st,RA[ind].w,1,n,1);                ind++;            }            LL tmp=seg.query(QA[i].st,QA[i].ed,1,n,1);            tmp=max(tmp,0LL);            ans[QA[i].w]=sum[QA[i].ed]-sum[QA[i].st]-tmp;        }        seg.build(1,n,1);        sort(QB.begin(),QB.end(),cmpST);        sort(RB.begin(),RB.end(),cmpST);        len1=(int)QB.size();        len2=(int)RB.size();        ind=0;        for(int i=0;i<len1;i++)        {            while(ind<len2&&RB[ind].st<=QB[i].st)            {                seg.updata(RB[ind].ed,RB[ind].w,1,n,1);                ind++;            }            LL tmp=seg.query(QB[i].ed,n,1,n,1);            ans[QB[i].w]=sum[n]-(sum[QB[i].ed]-sum[QB[i].st])-tmp;        }        for(int i=0;i<Q;i++) printf("%lld\n",ans[i]);    }return 0;}


原创粉丝点击