zoukankan      html  css  js  c++  java
  • 洛谷$P2605 [ZJOI2010]$基站选址 线段树优化$dp$

    正解:线段树优化$dp$

    解题报告:

    传送门$QwQ$

    难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$

    先考虑暴力$dp$?就设$f_{i,j}$表示选的第$j$个基站是$i$的最小费用,就有$f_{i,j}=min(f_{k,j}+cost(k,i))+c_i$,这个$cost$就$[k+1,i-1]$之间所有基站的补偿之和.

    发现这个$cost$并不好求?于是逆向思考,每次在决策完选$x$转移完之后就会进入不选$x$的阶段嘛(因为是,$j$在外层循环$i$在内层,也就每次只会选一个基站,所以决策完第$j$个选$x$后就会决策第$j$个选$x$之后的基站,那第$x$个基站就不会被选了$QwQ$),那就把$[1,x]$范围内所有因为不选$x$而导致代价增加的加上

    于是先预处理一个$st_{i}$和一个$ed_{i}$数组,表示能让$i$被覆盖的基站的编号范围,然后每次把所有$ed_{i}=x$的点找出来.但是发现当上一次选的点在$[st_{i},ed_{i}-1]$范围内的时候就依然没有关系,所以就只要$f_{[1,st[i]-1],j}+=w_i$

    现在就变成了区间加区间查询最小值,线段树维护就好,$over$

    #include<bits/stdc++.h>
    using namespace std;
    #define il inline
    #define gc getchar()
    #define t(i) edge[i].to
    #define ri register int
    #define rc register char
    #define rb register bool
    #define rp(i,x,y) for(ri i=x;i<=y;++i)
    #define my(i,x,y) for(ri i=x;i>=y;--i)
    #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt)
    #define lb(x) lower_bound(d+1,d+1+n,x)-d
    
    const int N=20000+10,inf=0x3f3f3f3f;
    int n,K,d[N],c[N],s[N],w[N],st[N],ed[N],tr[N<<2],tag[N<<2],ed_cnt,head[N],f[N],as;
    struct edg{int to,nxt;}edge[N];
    
    il int read()
    {
        rc ch=gc;ri x=0;rb y=1;
        while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
        if(ch=='-')ch=gc,y=0;
        while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
        return y?x:-x;
    }
    il void ad(ri x,ri y){edge[++ed_cnt]=(edg){x,head[y]};head[y]=ed_cnt;}
    void build(ri nw,ri l,ri r)
    {
        tag[nw]=0;if(l==r)return void(tr[nw]=f[l]);
        ri mid=(l+r)>>1;build(nw<<1,l,mid);build(nw<<1|1,mid+1,r);
        tr[nw]=min(tr[nw<<1],tr[nw<<1|1]);
    }
    il void pushdown(ri nw)
    {
        if(!tag[nw])return;
        tag[nw<<1]+=tag[nw];tag[nw<<1|1]+=tag[nw];tr[nw<<1]+=tag[nw];tr[nw<<1|1]+=tag[nw];tag[nw]=0;
    }
    void add(ri nw,ri l,ri r,ri to_l,ri to_r,ri dat)
    {
        if(to_l<=l && r<=to_r){tr[nw]+=dat;tag[nw]+=dat;return;}//return void(tr[nw]+=dat,tag[nw]+=dat);
        pushdown(nw);ri mid=(l+r)>>1;
        if(mid>=to_l)add(nw<<1,l,mid,to_l,to_r,dat);if(mid<to_r)add(nw<<1|1,mid+1,r,to_l,to_r,dat);
        tr[nw]=min(tr[nw<<1],tr[nw<<1|1]);
    }
    int query(ri nw,ri l,ri r,ri to_l,ri to_r)
    {
    //    printf("nw=%d l=%d r=%d to_l=%d to_r=%d
    ",nw,l,r,to_l,to_r);
        if(to_l<=l && r<=to_r)return tr[nw];
        pushdown(nw);ri mid=(l+r)>>1,ret=inf;
        if(mid>=to_l)ret=query(nw<<1,l,mid,to_l,to_r);if(mid<to_r)ret=min(ret,query(nw<<1|1,mid+1,r,to_l,to_r));
    //    printf("[%d,%d]:%d
    ")
        return ret;
    }
    
    int main()
    {
    //    freopen("2605.in","r",stdin);//freopen("2605.out","w",stdout);
        n=read();K=read()+1;rp(i,2,n)d[i]=read();rp(i,1,n)c[i]=read();rp(i,1,n)s[i]=read();rp(i,1,n)w[i]=read();++n;d[n]=w[n]=inf;
        rp(i,1,n){st[i]=lb(d[i]-s[i]);ed[i]=lb(d[i]+s[i]);if(d[ed[i]]>d[i]+s[i])--ed[i];ad(i,ed[i]);}
        ri ret=0;rp(i,1,n){f[i]=ret+c[i];e(j,i)ret+=w[t(j)];}as=f[n];
        rp(i,2,K)
        {
            build(1,1,n);
            rp(j,1,n)
            {
                f[j]=(j>i-1?query(1,1,n,i-1,j-1):0)+c[j];//printf("f[%d]=%d=%d+%d
    ",j,f[j],j>i-1?query(1,1,n,1,j-1):0,c[j]);
                e(k,j)if(st[t(k)]>1)add(1,1,n,1,st[t(k)]-1,w[t(k)]);
            }
            as=min(as,f[n]);
        }
        printf("%d
    ",as);
        return 0;
    }
    View Code
  • 相关阅读:
    错误处理
    文件系统API
    promise A
    #每日总结#3
    CSS3秘笈复习:十三章&十四章&十五章&十六章&十七章
    CSS3秘笈复习:第十一章
    CSS3秘笈复习:第九章&第十章
    CSS3秘笈复习:第八章
    CSS3秘笈复习:第七章
    CSS3秘笈复习:第六章
  • 原文地址:https://www.cnblogs.com/lqsukida/p/11577575.html
Copyright © 2011-2022 走看看