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