[CF587-F]WI-FI

显然DP题...

f[i][0]表示这个点不装路由器,f[i][1]表示装路由器

转移也很简单,在前面一段区间找最小值就好了

但是直接转移是$O(n*k)$的,会T掉

大佬说这个东西有单调性,但是菜鸡我找不到,因为是区间问题,所以线段树强上

区间查询+单点修改

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define inf (0x7f7f7f7f7f7f7f)
 4 using namespace std;
 5 inline int read(){
 6     int ans=0,f=1;char chr=getchar();
 7     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
 8     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
 9     return ans*f;
10 }const int M = 2e5+5;
11 struct Segment_Tree{
12     int s[M<<2];
13     #define mid (l+r>>1)
14     #define ls (i<<1)
15     #define rs (i<<1|1)
16     inline void Push_Up(int i){s[i]=min(s[ls],s[rs]);}
17     void Build(int i,int l,int r){
18         if(l==r)return (void)(s[i]=inf);
19         Build(ls,l,mid),Build(rs,mid+1,r);
20         Push_Up(i);
21     }void Update(int i,int l,int r,int pos,int x){
22         if(l==r)return (void)(s[i]=min(s[i],x));
23         if(pos<=mid) Update(ls,l,mid,pos,x);
24         else Update(rs,mid+1,r,pos,x);
25         Push_Up(i);
26     }int Query(int i,int l,int r,int ql,int qr){
27         if(ql<=l&&r<=qr)return s[i];
28         int t1=inf,t2=inf;
29         if(ql<=mid) t1=Query(ls,l,mid,ql,qr);
30         if(qr>mid)  t2=Query(rs,mid+1,r,ql,qr);
31         return min(t1,t2);
32     }
33 }T1,T2;
34 char s[M];
35 int n,m,k,f[M][2];
36 signed main(){
37     n=read(),k=read();
38     scanf("%s",s+2);
39     T1.Build(1,1,n),T2.Build(1,1,n);
40     memset(f,0x3f,sizeof(f));
41     T2.Update(1,1,n,1,f[1][0]=f[1][1]=0);
42     for(int i=2;i<=n+1;i++){
43         f[i][0]=T1.Query(1,1,n,max(i-k,1ll),i-1);
44         if(s[i]=='1') f[i][1]=T2.Query(1,1,n,max(1ll,i-k-1),i-1)+i-1;
45         else f[i][1]=min(T1.Query(1,1,n,max(1ll,i-k-1),i-1),min(f[i-1][0],f[i-1][1]))+i-1;
46         T2.Update(1,1,n,i,min(f[i][0],f[i][1]));
47         if(s[i]=='1') T1.Update(1,1,n,i,f[i][1]);
48     }cout<<min(f[n+1][0],f[n+1][1]);
49     return 0;
50 }

 

posted @ 2019-09-22 16:02  zheng_liwen  阅读(385)  评论(0编辑  收藏  举报
/*去广告*/