zoukankan      html  css  js  c++  java
  • [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而被覆盖,现在却不能被覆盖的点,就需要k来覆盖它。我们定义L[i],R[i],分别表示i最左边能覆盖i的点,和最右边的。于是每次对于R[x]=i的点,1~L[x]-1的点的cost都要加上w[x]。于是我们可以用一个线段树维护min(f[k][j-1]+cost(k,i)),求L[i]和R[i]二分就好。

    注意一个细节,因为我们并不知道最后一个站建在哪,所以可以手动加一个点,令他的w=inf,c=0,d=inf,s=0,这样就一定会选它了。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    typedef long long LL;
    using namespace std;
    const int N=200010,inf=1e9;
    struct node{int l,r,v,lazy;}a[N<<4];
    int n,m,d[N],w[N],s[N],c[N],f[N],L[N],R[N];
    vector<int>vec[N];
    inline int read() {int d=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=(d<<3)+(d<<1)+c-48,c=getchar(); return d*f;}
    void judge(){freopen(".in","r",stdin); freopen(".out","w",stdout);}
    inline void pushup(int k){a[k].v=min(a[k<<1].v,a[k<<1|1].v);}
    inline void pushdown(int k)
    {
        if (!a[k].lazy) return;
        int k1=k<<1,k2=k1|1;
        a[k1].lazy+=a[k].lazy; a[k2].lazy+=a[k].lazy;
        a[k1].v+=a[k].lazy; a[k2].v+=a[k].lazy;
        a[k].lazy=0;
    }
    inline void build(int k,int l,int r)
    {
        a[k]=(node){l,r,0,0};
        if (l==r) {a[k].v=f[l]; return;}
        int mid=(l+r)>>1;
        build(k<<1,l,mid); build(k<<1|1,mid+1,r);
        pushup(k);
    }
    inline void update(int k,int l,int r,int v)
    {
        if (l>r) return;
        if (l<=a[k].l&&a[k].r<=r) {a[k].v+=v; a[k].lazy+=v; return;}
        pushdown(k);
        int mid=(a[k].l+a[k].r)>>1;
        if (r<=mid) update(k<<1,l,r,v);
        else if (l>mid) update(k<<1|1,l,r,v);
        else update(k<<1,l,mid,v),update(k<<1|1,mid+1,r,v);
        pushup(k);
    }
    inline int query(int k,int l,int r)
    {
        if (l>r) return 0;
        if (l<=a[k].l&&a[k].r<=r) return a[k].v;
        pushdown(k);
        int mid=(a[k].l+a[k].r)>>1;
        if (r<=mid) return query(k<<1,l,r);
        else if (l>mid) return query(k<<1|1,l,r);
        else return min(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
    }
    int main()
    {
        //judge();
        n=read(); m=read();
        for (int i=2;i<=n;i++) d[i]=read();
        for (int i=1;i<=n;i++) c[i]=read();
        for (int i=1;i<=n;i++) s[i]=read();
        for (int i=1;i<=n;i++) w[i]=read();
        n++; d[n]=inf; c[n]=0; s[n]=0; w[n]=inf;
        for (int i=1;i<=n;i++)
        {
            L[i]=lower_bound(d+1,d+1+n,d[i]-s[i])-d;
            R[i]=lower_bound(d+1,d+1+n,d[i]+s[i])-d;
            if (d[R[i]]>d[i]+s[i]) R[i]--;
            vec[R[i]].push_back(i);
        }
        int ljj=0;
        for (int i=1;i<=n;i++)
        {
            f[i]=ljj+c[i];
            for (int j=0;j<vec[i].size();j++) ljj+=w[vec[i][j]];
        }
        int ans=f[n];
        for (ljj=1;ljj<=m;ljj++)
        {
            build(1,1,n);
            for (int i=1;i<=n;i++)
            {
                f[i]=query(1,1,i-1)+c[i];
                for (int j=0;j<vec[i].size();j++)
                {
                    int k=vec[i][j];
                    update(1,1,L[k]-1,w[k]);
                }
            }
            ans=min(ans,f[n]);
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    话说stl是真方便!

    注:ZJOI2009的题好鬼畜啊,不想做了,07,08的不写题解了,可以看小乐乐的博客:http://blog.163.com/eden_284914869/

  • 相关阅读:
    小结css2与css3的区别
    javascript变量的作用域
    javascript面向对象
    小结php中几种网页跳转
    foreach
    post与get,这两人到底神马区别??
    typescript遍历Map
    dataTable.js参数
    showModal()和show()的区别
    javascript中location.protocol、location.hostname和location.port
  • 原文地址:https://www.cnblogs.com/lujiaju6555/p/6788926.html
Copyright © 2011-2022 走看看