2 条题解

  • 0
    @ 2025-10-8 17:14:26

    简化一下题意: 给定一个长为 n 的字符串 s,表示 n 段时间,有三种情况,分别表示线上会议,线下会议和空闲时间; 线下会议只能在公司参加,线上会议在公司和家中均可参加,空闲时间可以做题 可以选择使用 t 段时间通勤去到公司,但只能去一次,且通勤时间能不能做题也不能参加会议 注意最后必须回到家中,所以必然会有两段通勤时间 总共可以翘掉 k 次会议,只有空闲时间或者被翘掉且不在通勤的时间可以做题


    读完了题意后,这道题的大致轮廓就比较清晰了 我们可以发现由于只能去公司一次,所以只要确定了通勤时间后做题时间可以通过前缀和直接计算 计算过程就是把通勤时间内的会议数量 cnt 先和 k 作比较,然后大于就直接略过,小于就让 k 直接减去 cnt 然后对于通勤时间和在公司时间外的所有线下会议数量 cnt1 和 剩余的 k 作比较,小于也是直接略过不考虑,然后让剩余的 k 减一次 cnt1 接着就是把剩下空闲的时间和剩余可以被翘掉的会议加到答案中 可以发现此题数据不大,所以直接枚举通勤的时间然后比较计算最大即可 代码如下:

    #include<bits/stdc++.h>
    #define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
    using namespace std;
    const int N=8001;
    int n,k,t,pre1[N],pre2[N],pre3[N],mx=-1;
    string s;
    int gt_sm(int op,int l,int r){
    	if(op==1)return pre1[r]-pre1[l-1];
    	else if(op==2)return pre2[r]-pre2[l-1];
    	else return pre3[r]-pre3[l-1];
    }
    int solve(int l,int r){
    	int res,tk=k,cnt;
    	tk-=gt_sm(1,l-t,l-1)+gt_sm(2,l-t,l-1);
    	tk-=gt_sm(1,r+1,r+t)+gt_sm(2,r+1,r+t);
    	if(tk<0)return -1;
    	l-=t+1,r=min(n+1,r+t+1);
    	res=gt_sm(3,1,l)+gt_sm(3,r,n);
    	cnt=gt_sm(1,1,l)+gt_sm(1,r,n);
    	if(tk<cnt)return -1;
    	cnt+=gt_sm(2,1,l)+gt_sm(2,r,n);
    	return res+min(cnt,tk);
    }
    int main(){
    	ios;
    	cin>>n>>k>>t>>s;
    	for(int i=1;i<=n;++i){
    		pre1[i]=pre1[i-1],pre2[i]=pre2[i-1],pre3[i]=pre3[i-1];
    		if(s[i-1]=='1')pre1[i]++;
    		else if(s[i-1]=='2')pre2[i]++;
    		else pre3[i]++;
    	}
    	if(k>=pre1[n])cout<<min(n,k+pre3[n]),exit(0);
    	for(int i=t+1;i<=n-t+1;++i)
    		for(int j=i;j<=n-t;++j)
    			mx=max(mx,solve(i,j));
    	cout<<mx;
    }
    
    • 0
      @ 2025-10-8 17:14:10
      简化一下题意:                 
      给定一个长为 $n$ 的字符串 $s$,表示 $n$ 段时间,有三种情况,分别表示线上会议,线下会议和空闲时间;
      线下会议只能在公司参加,线上会议在公司和家中均可参加,空闲时间可以做题             
      可以选择使用 $t$ 段时间通勤去到公司,但只能去一次,且通勤时间能不能做题也不能参加会议                           
      **注意最后必须回到家中,所以必然会有两段通勤时间**                    
      总共可以翘掉 $k$ 次会议,只有空闲时间或者被翘掉且不在通勤的时间可以做题    
      
      
      ---
      
      读完了题意后,这道题的大致轮廓就比较清晰了             
      我们可以发现由于**只能去公司一次**,所以只要确定了通勤时间后做题时间可以通过前缀和直接计算   
      计算过程就是把通勤时间内的会议数量 $cnt$ 先和 $k$ 作比较,然后大于就直接略过,小于就让 $k$ 直接减去 $cnt$ 然后对于通勤时间和在公司时间外的所有线下会议数量 $cnt1$ 和 剩余的 $k$ 作比较,小于也是直接略过不考虑,然后让剩余的 $k$ 减一次 $cnt1$ 接着就是把剩下空闲的时间和剩余可以被翘掉的会议加到答案中        
      可以发现此题数据不大,所以直接枚举通勤的时间然后比较计算最大即可                
      代码如下:
      
      
      #include<bits/stdc++.h>
      #define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
      using namespace std;
      const int N=8001;
      int n,k,t,pre1[N],pre2[N],pre3[N],mx=-1;
      string s;
      int gt_sm(int op,int l,int r){
      	if(op==1)return pre1[r]-pre1[l-1];
      	else if(op==2)return pre2[r]-pre2[l-1];
      	else return pre3[r]-pre3[l-1];
      }
      int solve(int l,int r){
      	int res,tk=k,cnt;
      	tk-=gt_sm(1,l-t,l-1)+gt_sm(2,l-t,l-1);
      	tk-=gt_sm(1,r+1,r+t)+gt_sm(2,r+1,r+t);
      	if(tk<0)return -1;
      	l-=t+1,r=min(n+1,r+t+1);
      	res=gt_sm(3,1,l)+gt_sm(3,r,n);
      	cnt=gt_sm(1,1,l)+gt_sm(1,r,n);
      	if(tk<cnt)return -1;
      	cnt+=gt_sm(2,1,l)+gt_sm(2,r,n);
      	return res+min(cnt,tk);
      }
      int main(){
      	ios;
      	cin>>n>>k>>t>>s;
      	for(int i=1;i<=n;++i){
      		pre1[i]=pre1[i-1],pre2[i]=pre2[i-1],pre3[i]=pre3[i-1];
      		if(s[i-1]=='1')pre1[i]++;
      		else if(s[i-1]=='2')pre2[i]++;
      		else pre3[i]++;
      	}
      	if(k>=pre1[n])cout<<min(n,k+pre3[n]),exit(0);
      	for(int i=t+1;i<=n-t+1;++i)
      		for(int j=i;j<=n-t;++j)
      			mx=max(mx,solve(i,j));
      	cout<<mx;
      }
      • 1

      信息

      ID
      7668
      时间
      8000ms
      内存
      256MiB
      难度
      10
      标签
      递交数
      4
      已通过
      3
      上传者