F. Wi-Fi
题意:
输入
n
,
k
(
2
e
5
)
n,k(2e5)
n,k(2e5),表示有
n
n
n个连续的房间,路由器的左右延伸范围为
k
k
k;
第二行输入一个长度为
n
n
n的
01
01
01字符串
s
s
s,为1表示该房间能放路由器,否则不能放路由器。
现要把所有房间于互联网相连(可以直接相连或于路由器相连),房间
i
i
i和互联网或放路由器直接相连花费
i
i
i,问最小花费是多少。
题解:
首先分析对于能放路由器的房间绝不和互联网直接相连;
定义:
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]为
1
−
i
1-i
1−i房间与互联网相连且
i
i
i房间不放路由器的最小花费。
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1]为
1
−
i
1-i
1−i房间与互联网相连且
i
i
i房间放路由器的最小花费。
转移:
d
p
[
i
]
[
0
]
=
m
i
n
(
d
p
[
i
−
1
]
[
0
]
+
i
,
m
i
n
j
=
m
a
x
(
1
,
i
−
k
)
i
−
1
d
p
[
j
]
[
1
]
)
dp[i][0]=min(dp[i-1][0]+i,min_{j=max(1,i-k)}^{i-1}dp[j][1])
dp[i][0]=min(dp[i−1][0]+i,minj=max(1,i−k)i−1dp[j][1])
d
p
[
i
]
[
1
]
=
i
+
m
i
n
(
d
p
[
m
a
x
(
i
−
k
−
1
,
0
)
]
[
0
]
,
m
i
n
j
=
m
a
x
(
i
−
k
−
1
,
0
)
i
−
1
(
d
p
[
j
]
[
1
]
)
)
dp[i][1]=i+min(dp[max(i-k-1,0)][0],min_{j=max(i-k-1,0)}^{i-1}(dp[j][1]))
dp[i][1]=i+min(dp[max(i−k−1,0)][0],minj=max(i−k−1,0)i−1(dp[j][1]))
代码:
#include<bits/stdc++.h>
//#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
using namespace std;
#define ll long long
const int N=2e5+9;
ll dp[N][2];
int n,k;string s;
ll mn[N<<2];
void update(int p,int l,int r,int qx,ll qz){
if(l==r)mn[p]=qz;
else{
int mid=(l+r)>>1;
if(qx<=mid)update(ls(p),l,mid,qx,qz);
else update(rs(p),mid+1,r,qx,qz);
mn[p]=min(mn[ls(p)],mn[rs(p)]);
}
}
ll query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return mn[p];
else{
int mid=(l+r)>>1;
ll mn=1e18;
if(ql<=mid)mn=min(mn,query(ls(p),l,mid,ql,qr));
if(qr>mid)mn=min(mn,query(rs(p),mid+1,r,ql,qr));
return mn;
}
}
signed main(){
//freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
cin>>n>>k>>s;s=" "+s;
memset(dp,0x3f,sizeof(dp));memset(mn,0x3f,sizeof(mn));
dp[0][0]=0;
ll mnn=1e18;
// cout<<n<<endl;
for(int i=1;i<=n;i++){
// dp[i][0]=dp[i-1][0]+i;
dp[i][0]=min(dp[i-1][0]+i,query(1,1,n,max(1,i-k),i));
if(s[i]=='1'){
int low=max(i-k-1,0);
dp[i][1]=min(dp[low][0],query(1,1,n,low,i))+i;
update(1,1,n,i,dp[i][1]);
}
}
// for(int i=1;i<=n;i++)
// for(int j=0;j<=1;j++)printf("dp[%d][%d]=%lld\n",i,j,dp[i][j]);
mnn=min(dp[n][0],dp[n][1]);
cout<<mnn<<endl;
return 0;
}