首先要计算出每一条路最早开始的那一天,然后最晚结束的那一天。
这些天之间这条边都必须$open$,然后就变成一个线段树区间$+val$的问题了,最后询问一个每个点的$val$是多少。
注意:数据中有$ai>bi$的情况。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> #include<ctime> using namespace std; typedef long long LL; const double pi=acos(-1.0); void File() { freopen("D:\in.txt","r",stdin); freopen("D:\out.txt","w",stdout); } const int maxn=200010; int T,n,m,w[maxn]; struct X{ int u,v; }p[maxn]; int L[maxn],R[maxn]; int s[4*maxn]; void build(int l,int r,int rt) { s[rt]=0; if(l==r) return; int m=(l+r)/2; build(l,m,2*rt); build(m+1,r,2*rt+1); } void update(int L,int R,int x,int l,int r,int rt) { if(L<=l&&r<=R) { if(s[rt]==0) s[rt]=x; return; } if(s[rt]!=0) { if(s[2*rt]==0) s[2*rt]=s[rt]; if(s[2*rt+1]==0) s[2*rt+1]=s[rt]; } int m=(l+r)/2; if(L<=m) update(L,R,x,l,m,2*rt); if(R>m) update(L,R,x,m+1,r,2*rt+1); } int get(int pos,int l,int r,int rt) { if(l==r) { return s[rt]; } if(s[2*rt]==0) s[2*rt]=s[rt]; if(s[2*rt+1]==0) s[2*rt+1]=s[rt]; int m =(l+r)/2; if(l<=pos&&pos<=m) return get(pos,l,m,2*rt); else return get(pos,m+1,r,2*rt+1); } void ADD(int L,int R,int x,int l,int r,int rt) { if(L<=l&&r<=R) { s[rt]+=x; return; } int m=(l+r)/2; if(L<=m) ADD(L,R,x,l,m,2*rt); if(R>m) ADD(L,R,x,m+1,r,2*rt+1); } int quary(int pos,int l,int r,int rt) { if(l==r) return s[rt]; if(s[rt]!=0) { s[2*rt]+=s[rt]; s[2*rt+1]+=s[rt]; s[rt]=0; } int m =(l+r)/2; if(l<=pos&&pos<=m) return quary(pos,l,m,2*rt); else return quary(pos,m+1,r,2*rt+1); } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n-1; i++) scanf("%d",&w[i]); for(int i=1; i<=m; i++) { scanf("%d%d",&p[i].u,&p[i].v); if(p[i].v<p[i].u) swap(p[i].v,p[i].u); } build(1,n,1); for(int i=1; i<=m; i++) update(p[i].u,p[i].v-1,i,1,n,1); for(int i=1; i<=n-1; i++) L[i]=get(i,1,n,1); build(1,n,1); for(int i=m; i>=1; i--) { update(p[i].u,p[i].v-1,i,1,n,1); } for(int i=1; i<=n-1; i++) R[i]=get(i,1,n,1); build(1,m,1); for(int i=1;i<=n-1;i++) { if(L[i]==0||R[i]==0) continue; ADD(L[i],R[i],w[i],1,m,1); } for(int i=1;i<=m;i++) printf("%d ",quary(i,1,m,1)); } return 0; }