BZOJ 1835 基站选址(DP+线段树)

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-9
# define MOD 1024523
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
void Out(int a) {
    if(a<0) {putchar(‘-‘); a=-a;}
    if(a>=10) Out(a/10);
    putchar(a%10+‘0‘);
}
const int N=20005;
//Code begin...

int n, k, d[N], c[N], s[N], w[N], bg[N], ed[N], seg[N<<3], tag[N<<3];
VI v[N];
LL dp[N];

void _init(){
    FOR(i,1,n) {
        int l=d[i]-s[i], r=d[i]+s[i];
        l=lower_bound(d+1,d+n+1,l)-d; r=lower_bound(d+1,d+n+1,r)-d;
        if (d[r]>d[i]+s[i]) --r;
        bg[i]=l; ed[i]=r; v[r].pb(i);
    }
}
void push_up(int p){seg[p]=min(seg[p<<1],seg[p<<1|1]);}
void push_down(int p){
    if (!tag[p]) return ;
    seg[p]+=tag[p]; tag[p<<1]+=tag[p]; tag[p<<1|1]+=tag[p]; tag[p]=0;
}
void init(int p, int l, int r){
    if (l<r) {
        int mid=(l+r)>>1;
        tag[p]=0; init(lch); init(rch); push_up(p);
    }
    else seg[p]=dp[l], tag[p]=0;
}
int query(int p, int l, int r, int L, int R){
    push_down(p);
    if (L>r||R<l) return INF;
    if (L<=l&&R>=r) return seg[p];
    int mid=(l+r)>>1;
    return min(query(lch,L,R),query(rch,L,R));
}
void update(int p, int l, int r, int L, int R, int val){
    push_down(p);
    if (L>r||R<l) return ;
    if (L<=l&&R>=r) tag[p]=val, push_down(p);
    else {
        int mid=(l+r)>>1;
        update(lch,L,R,val); update(rch,L,R,val); push_up(p);
    }
}
int main ()
{
    scanf("%d%d",&n,&k);
    FOR(i,2,n) scanf("%d",d+i); FOR(i,1,n) scanf("%d",c+i);
    FOR(i,1,n) scanf("%d",s+i); FOR(i,1,n) scanf("%d",w+i);
    ++n; ++k; d[n]=INF; w[n]=INF;
    _init();
    LL ans, tmp=0;
    FOR(i,1,n) {
        dp[i]=tmp+c[i];
        FO(j,0,v[i].size()) tmp+=w[v[i][j]];
    }
    ans=dp[n];
    FOR(i,2,k) {
        init(1,1,n);
        FOR(j,1,n) {
            dp[j]=(j>1?query(1,1,n,1,j-1):0)+c[j];
            FO(l,0,v[j].size()) if (bg[v[j][l]]>1) update(1,1,n,1,bg[v[j][l]]-1,w[v[j][l]]);
        }
        ans=min(ans,dp[n]);
    }
    printf("%lld\n",ans);
    return 0;
}

时间: 2024-08-10 00:05:38

BZOJ 1835 基站选址(DP+线段树)的相关文章

BZOJ 1835 基站选址(线段树优化DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1835 题意:有N个村庄坐落在一条直线上,第 i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村 庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了.如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi.现在的问题是,选择基站的位 置,使得总费用最小. 思路: 另外,程序中的n=n+1,m=

[BZOJ1835][ZJOI2010]base 基站选址(DP+线段树)

首先想到DP,f[i][j]表示前i个村庄,共建了j个站的最小费用,且第j个站建在第i个村庄上 f[i][j]=min(f[i][j],f[k][j-1]+cost(k,i));(1<=k<i) cost(k,i)表示选了k和i之后,他们之间需要的w的和 然后这样是O(kn^2)的,对于100%的数据会T.我们可以发现瓶颈在于找到min(f[k][j-1]+cost(k,i)),考虑如何优化它.还有显然的是可以舍掉第二维,只要先枚举建的站的数量即可. 当i变为i+1时,对于那些原来能建立了i而

bzoj 1835 基站选址(线段树优化Dp)

Description 题意:有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di 需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci 如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了 如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi 现在的问题是,选择基站的位置,使得总费用最小. Solution 首先可以想到dp,用dp[i][j]表示前i个村庄建了j个通讯站且第j个建在i处 dp[i][j]=min(dp[k][

[ZJOI2010]基站选址(线段树优化dp)

坑待填. \(Code\ Below:\) #include <bits/stdc++.h> #define lson (rt<<1) #define rson (rt<<1|1) using namespace std; const int maxn=20000+10; const int inf=0x3f3f3f3f; int n,k,d[maxn],c[maxn],s[maxn],w[maxn],f[maxn],st[maxn],ed[maxn],sum[maxn

题解 HDU 3698 Let the light guide us Dp + 线段树优化

http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 62768/32768 K (Java/Others) Total Submission(s): 759    Accepted Submission(s): 253 Problem Description Plain of despair was

BZOJ 3211 花神游历各国 线段树题解

BZOJ 3211 花神游历各国 线段树题解 3211: 花神游历各国 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2551  Solved: 946[Submit][Status][Discuss] Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 2 3 1 1 4 Sample Output 101

[后缀数组+dp/AC自动机+dp+线段树] hdu 4117 GRE Words

题意: 给你N个字符串, N(1 <= N <= 2w), 所有串的长度加一起不超过30w.每个串有个值.这个值[-1000, 1000]. 问不打乱字符串顺序,从中取若干个字符串,使得前一个串是后一个串的子串,求满足前面调条件的字符串值得和最大,求这个值. 思路: 其实就是一个很明显的dp. dp[i]代表以第i个字符串结尾的最大权值. 但是就是子串这个问题怎么处理. 由于这题数据比较水可以用后缀数组处理这个问题. 将所有字符串拼接,做sa. 每次在height数组里往上和往下寻找公共前缀等

bzoj 1835 [ZJOI2010]base 基站选址(DP+线段树)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1835 [题意] 有n个村庄,每个村庄位于d[i],要求建立不多于k个基站,在第i个村庄建基站的费用为c[i],如果在距离村i不超过s[i]内有基站则该村被覆盖,村i不被覆盖的补偿费为w[i],求最少花费. [思路] 设f[i][j]表示第i个村建第j个基站的最小花费,则有转移式: f[i][j]=min{ f[k][j-1]+cost(k,i) } + c[i] ,j-1<=k<=

BZOJ 1852:[MexicoOI06]最长不下降序列(贪心+DP+线段树+离散化)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1852 [题目大意] 给你N对数A1,B1……An,Bn.要求你从中找出最多的对, 把它们按照一种方式排列,重新标号1,2,..,k.能满足对于每一对i<j,都有Ai>Bj. [题解] 对于排序的问题,如果i必须要在j前面, 那么有A[i]>B[j],且B[i]>=A[j],相加得A[i]+B[i]>A[j]+B[j], 因此按A+B从大到小排序后最优, 我们先将A