• BZOJ 1835 [ZJOI2010]base 基站选址


    题解:Dp+线段树维护所有决策

    f[i][j]表示第j个基站建在第i个位置,i之前的村庄与建基站的总费用的最小值

    以j为阶段

    枚举i,维护所有决策f[x][j-1];

    当一个村庄q不能被i覆盖了,那么在1~p之间建立基站的决策费用要+c

    p为q左边第一个不能覆盖q的村庄

    复杂度O( nklogn);

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=20009;
    const int inf=1000000000;
    
    int n,m;
    int ans=inf;
    int f[maxn][109];
    int d[maxn];
    int c[maxn];
    int w[maxn];
    int s[maxn];
    int Bl[maxn],Br[maxn];
    vector<int>Tr[maxn],Tl[maxn];
    
    struct SegmentTree{
    	int l,r,tag,mn;
    }tree[maxn<<2];
    inline void pushup(int now){
    	tree[now].mn=min(tree[now<<1].mn,tree[now<<1|1].mn);
    }
    inline void pushdown(int now){
    	if(tree[now].tag){
    		tree[now<<1].tag+=tree[now].tag;
    		tree[now<<1|1].tag+=tree[now].tag;
    		tree[now<<1].mn+=tree[now].tag;
    		tree[now<<1|1].mn+=tree[now].tag;
    		tree[now].tag=0;
    	}
    }
    void BuildTree(int now,int l,int r,int p){
    	tree[now].l=l;tree[now].r=r;tree[now].tag=0;
    	if(l==r){
    		tree[now].mn=f[l][p];
    		return;
    	}
    	int mid=(l+r)>>1;
    	BuildTree(now<<1,l,mid,p);
    	BuildTree(now<<1|1,mid+1,r,p);
    	pushup(now);
    }
    void Updatasec(int now,int ll,int rr,int x){
    	if(ll>rr)return;
    	if(tree[now].l>=ll&&tree[now].r<=rr){
    		tree[now].tag+=x;tree[now].mn+=x;return;
    	}
    	pushdown(now);
    	int mid=(tree[now].l+tree[now].r)>>1;
    	if(ll<=mid)Updatasec(now<<1,ll,rr,x);
    	if(rr>mid)Updatasec(now<<1|1,ll,rr,x);
    	pushup(now);
    }
    
    int Querymin(int now,int ll,int rr){
    	if(tree[now].l>=ll&&tree[now].r<=rr){
    		return tree[now].mn;
    	}
    	pushdown(now);
    	int mid=(tree[now].l+tree[now].r)>>1;
    	int ret=inf;
    	if(ll<=mid)ret=min(ret,Querymin(now<<1,ll,rr));
    	if(rr>mid)ret=min(ret,Querymin(now<<1|1,ll,rr));
    	return ret;
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	d[1]=0;
    	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",&w[i]);
    	for(int i=1;i<=n;++i){
    		int p,tmp;
    		tmp=d[i]+s[i];
    		p=lower_bound(d+1,d+1+n,tmp)-d;
    		if(tmp<=d[n]){
    			if(d[p]!=tmp)--p;
    			Tr[p].push_back(i);
    			Br[i]=p;
    		}else{
    			Br[i]=-1;
    		}
    		
    		tmp=d[i]-s[i];
    		p=lower_bound(d+1,d+1+n,tmp)-d;
    		if(tmp>=0){
    			Tl[p].push_back(i);
    			Bl[i]=p;
    		}else{
    			Bl[i]=-1;
    		}
    	}
    	
    //	for(int i=1;i<=n;++i){
    //		cout<<Bl[i]<<' '<<Br[i]<<endl;
    //	}
    	for(int tmp=0,i=1;i<=n;++i){
    //		cout<<"ASD"<<' '<<i<<' '<<tmp<<endl;
    		f[i][1]=tmp+c[i];
    		for(int j=0;j<Tr[i].size();++j){
    			int x=Tr[i][j];
    			tmp+=w[x];
    //			cout<<"eaint "<<tmp<<endl;
    		}
    	}
    	for(int j=2;j<=m;++j){
    		BuildTree(1,1,n,j-1);
    		for(int i=1;i<=j-1;++i)f[i][j]=inf;
    		for(int i=j;i<=n;++i){
    			f[i][j]=Querymin(1,1,i-1)+c[i];
    			for(int k=0;k<Tr[i].size();++k){
    				int x=Tr[i][k];
    				if(Bl[x]>1)Updatasec(1,1,Bl[x]-1,w[x]);
    			}
    		}
    	}
    	
    	for(int tmp=0,i=n;i>=1;--i){
    		for(int j=1;j<=m;++j){
    			ans=min(ans,f[i][j]+tmp);
    		}
    		for(int j=0;j<Tl[i].size();++j){
    			int x=Tl[i][j];
    			tmp+=w[x];
    		}
    	}
    //	for(int j=1;j<=m;++j){
    //		for(int i=1;i<=n;++i){
    //			cout<<f[i][j]<<' ';
    //		}
    //		cout<<endl;
    //	}
    	cout<<ans<<endl;
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    sqlldr、sqluldr2_w64案例
    查看oracle的sid和sevice_name
    杂记
    GAN学习
    Leetcode 第 217 场周赛
    牛客编程巅峰赛S2第4场
    SAR图像变化检测的一点想法
    Fire! UVA
    HDU
    HDU
  • 原文地址:https://www.cnblogs.com/zzyer/p/8455034.html
Copyright © 2020-2023  润新知