过了,但是不理解
查看原帖
过了,但是不理解
774854
qzmoot楼主2024/10/29 20:39

思路是如果从0转移说明这是第一个,多建了一个n+1号点,意思就是查询前面的所有最小值。

但是我们老师讲的是每一轮都要求一次min,因为不一定是建立k次,但是我却直接输出f[n]就通过了。

#include <bits/stdc++.h>
#define ls k<<1
#define rs k<<1|1
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define pb emplace_back
using namespace std;
const int N=2e4+5,inf=1e9;
int n,K;
struct node{
	int d,c,s,w;
}a[N];
struct tree{
	int mn,lz;
	tree(){mn=lz=0;}
}tr[N<<2];
int f[N];
void pu(int k)
{
	tr[k].mn=min(tr[ls].mn,tr[rs].mn);
}
void pd(int k)
{
	if(tr[k].lz)
	{
		tr[ls].lz+=tr[k].lz;
		tr[rs].lz+=tr[k].lz;
		tr[ls].mn+=tr[k].lz;
		tr[rs].mn+=tr[k].lz;
		tr[k].lz=0;
	}
}
void add(int k,int l,int r,int L,int R,int vl)
{
	if(L>R)
		return;
	if(R<l || r<L)
		return;
	if(L<=l && r<=R)
	{
		tr[k].mn+=vl;
		tr[k].lz+=vl;
		return;
	}
	pd(k);
	int mid=l+r>>1;
	add(ls,l,mid,L,R,vl);
	add(rs,mid+1,r,L,R,vl);
	pu(k);
}
int query(int k,int l,int r,int L,int R)
{
	if(R<l || r<L)
		return inf;
	if(L<=l && r<=R)
		return tr[k].mn;
	pd(k);
	int mid=l+r>>1;
	return min(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R));
}
int le[N],ri[N];
vector<pii>ned[N];
void build(int k,int l,int r)
{
	tr[k].lz=0;
	if(l==r)
	{
		tr[k].mn=f[l];
		return;
	}
	int mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pu(k);
}
int ans=inf;
int main()
{
	scanf("%d%d",&n,&K);
	a[1].d=0;
	for(int i=2;i<=n;i++)
		scanf("%d",&a[i].d);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i].c);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i].s);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i].w);
	n++;
	a[n].d=inf;
	a[n].w=inf;
	a[n].c=0;
	//puts("");
	for(int i=1;i<=n;i++)
	{
		int ll=a[i].d-a[i].s,rr=a[i].d+a[i].s;
		le[i]=1;
		for(int j=i;j>=1;j--)
			if(a[j-1].d<ll)
			{
				le[i]=j;
				break;
			}
		ri[i]=n;
		for(int j=i;j<=n;j++)
			if(a[j+1].d>rr)
			{
				ri[i]=j;
				break;
			}
		ned[ri[i]+1].pb(mp(le[i]-1,a[i].w));
		//cout<<le[i]<<' '<<ri[i]<<'\n';
	}
	//puts("");
	for(int i=1,sum=0;i<=n;i++)
	{
		f[i]=sum+a[i].c;
		for(auto v:ned[i])
			sum+=v.se;
	}
	for(int j=2;j<=K+1;j++)
	{
		build(1,0,n);
		for(int i=1;i<=n;i++)
		{
			for(auto v:ned[i])
				add(1,0,n,0,v.fi,v.se);
			f[i]=query(1,0,n,0,i-1)+a[i].c;
		}
		//ans=min(ans,f[n]);
	}
	printf("%d",f[n]);
	return 0;
}
2024/10/29 20:39
加载中...