记录编号 382558 评测结果 AAAAAAAAAA
题目名称 [ZJOI 2010] 基站选址 最终得分 100
用户昵称 GravatarAntiLeaf 是否通过 通过
代码语言 C++ 运行时间 2.671 s
提交时间 2017-03-14 08:03:21 内存使用 9.83 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20010,maxk=110;
struct A{
	int l,r,w;
	bool operator<(const A &a)const{return r<a.r;}
}a[maxn];
void build(int,int,int);
void modify(int,int,int,int,int,int);
int query(int,int,int,int,int);
int mn[maxn<<2],lazy[maxn<<2];
int d[maxn],c[maxn],s[maxn],w[maxn];
int n,m,k,f[maxn][maxk],ans=0;
int main(){
	freopen("base.in","r",stdin);
	freopen("base.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=2;i<=n;i++)scanf("%d",&d[i]);
	for(int i=1;i<=n;i++)scanf("%d",&c[i]);
	for(int i=1;i<=n;i++)scanf("%d",&s[i]);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i].w);
		a[i].l=lower_bound(d+1,d+n+1,d[i]-s[i])-d;
		a[i].r=upper_bound(d+1,d+n+1,d[i]+s[i])-d-1;
		f[a[i].r+1][1]+=a[i].w;
		w[a[i].l-1]+=a[i].w;
		ans+=a[i].w;//printf("l=%d r=%d w=%d\n",a[i].l,a[i].r,a[i].w);
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)f[i][1]+=f[i-1][1];
	for(int i=n;i;i--)w[i]+=w[i+1];
	for(int i=1;i<=n;i++){
		f[i][1]+=c[i];
		ans=min(ans,f[i][1]+w[i]);
	}
	//for(int i=1;i<=n;i++)printf("f[%d][0]=%d w=%d\n",i,f[i][0],w[i]);
	f[1][1]=c[1];
	for(k=2;k<=m;k++){
		int cur=1;
		build(1,n,1);
		for(int i=k;i<=n;i++){
			while(cur<=n&&a[cur].r<i){
				if(a[cur].l>=k)modify(k-1,a[cur].l-1,a[cur].w,1,n,1);//printf("%d~%d += %d\n",1,a[cur].l-1,a[cur].w);
				cur++;
			}
			f[i][k]=query(k-1,i-1,1,n,1)+c[i];//printf("f[%d][%d]=%d c[i]=%d\n",i,k,f[i][k],c[i]);
			ans=min(ans,f[i][k]+w[i]);
		}
	}
	printf("%d",ans);
	return 0;
}
void build(int l,int r,int rt){
	lazy[rt]=0;
	if(l==r){
		mn[rt]=f[l][k-1];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	mn[rt]=min(mn[rt<<1],mn[rt<<1|1]);
}
void modify(int s,int t,int d,int l,int r,int rt){
	if(s<=l&&t>=r){
		mn[rt]+=d;
		lazy[rt]+=d;
		return;
	}
	int mid=(l+r)>>1;
	if(s<=mid)modify(s,t,d,l,mid,rt<<1);
	if(t>mid)modify(s,t,d,mid+1,r,rt<<1|1);
	mn[rt]=min(mn[rt<<1],mn[rt<<1|1])+lazy[rt];
}
int query(int s,int t,int l,int r,int rt){
	if(s<=l&&t>=r)return mn[rt];
	int mid=(l+r)>>1;
	if(t<=mid)return query(s,t,l,mid,rt<<1)+lazy[rt];
	if(s>mid)return query(s,t,mid+1,r,rt<<1|1)+lazy[rt];
	return min(query(s,t,l,mid,rt<<1),query(s,t,mid+1,r,rt<<1|1))+lazy[rt];
}
/*
5 2
1 7 13 17
5 3 6 4 1
7 9 8 0 2
9 5 6 4 3
*/