题意: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; }