70pts WA求助
查看原帖
70pts WA求助
240480
lzx2007楼主2023/10/18 21:26

70pts

大概想法是先把原图刷成全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;
}
2023/10/18 21:26
加载中...