
大概想法是先把原图刷成全0。
处理在每个点,这个点前面都用操作一,剩下的用操作二,处理st[i][0],用st快速处理[l,r]每个点上的最小值。
接下来进行反悔操作(在全0上面加1) f[]为前面的操作一,直接+c[p], g[]为后面反悔操作二,-b[p]。
#include<iostream>
#include<vector>
using namespace std;
#define pb push_back
typedef long long lint;
const int MM=19, MN=(1<<19)+5;
const lint INF=1LL<<60;
inline void gmn(lint&x, lint y) { if(x>y) x=y; }
inline lint mn(lint x, lint y) { return (x<y?x:y); }
inline int reads() {
char c=getchar(); register int ans=0;
while( c< '0' || c> '9') c=getchar();
while( c>='0' && c<='9') ans=(ans<<3)+(ans<<1)-'0'+c, c=getchar();
return ans;
}
int a[MN], b[MN], c[MN];
lint d[MN], f[MN];
lint st[MN][MM], tmx[MN];
inline lint get(int l, int r) { int dt=tmx[r-l]; return mn(st[l][dt], st[r-(1<<dt)+1][dt]); }
int main() {
int i, k, dt, j;
int n=reads(), m, x, q;
tmx[1]=0; for(i=2; i<=n; i++) tmx[i]=tmx[i>>1]+1;
for(i=1; i<=n; i++) a[i]=reads();
for(i=1; i<=n; i++) b[i]=reads();
for(i=1; i<=n; i++) c[i]=reads();
for(i=n; i>=1; i--) d[i]=d[i+1]+b[i], st[i][0]=d[i]+a[i-1];
st[0][0]=d[1]; st[n+1][0]=a[n];
//for(i=1; i<=n; i++) printf("%d ", d[i]);
//printf("\n");
//for(i=1; i<=n+1; i++) printf("%d ", st[i][0]);
//printf("\n");
for(k=1, dt=1; dt<=n+1; k++, dt<<=1) for(i=0, j=dt; i<=n+1; i++, j+=(j<=n))
st[i][k]=mn(st[i][k-1], st[j][k-1]);
q=reads();
while(q--) {
lint ans=INF;
vector<int> g; m=reads(); g.pb( 0 );
while(m--) g.pb(reads()); g.pb(n+1);
int len=g.size()-1; i=0; d[len+1]=0;
for(i=len; i>=0; i--) d[i]=d[i+1]-b[g[i]];
for(i=1; i<=len; i++) f[i]=f[i-1]+c[g[i]],
//printf(" %d + %d + %d\n", f[i-1], d[i], get(g[i-1], g[i])),
gmn(ans, f[i-1]+d[i]+get(g[i-1], g[i]));
printf("%lld\n", ans);
}
return 0;
}