1 条题解
-
0
题意
每次消除 个砖,其中 块白色, 块黑色,并且这 块砖从开始到结束,中间不能路过已经消除过的砖。
思路
对照样例,不难想到了一点:如果某连续的一段是可消除的,则可以将这一段放到最后再消除。
这是样例输出:
1 8 12 2 6 7 3 4 5 9 10 11图示:

最后两步消除的部分都是连续段。由此或许可以看出一些性质?
我们考虑递归:
- 对于一个可以消除的连续子段,我们将它放在最后消除显然是可行的。
- 考虑时光倒流,消除了这个连续子段后将其直接丢掉,这样导致的结果就是会出现新的可以消除的连续子段,我们再将其放在序列中上一次的消除操作的前一次操作,这样就恰好可以满足条件了。
这么看来,我们的操作序列就是一个栈,同时我们可以在输入的过程中也实现一个栈,以便于我们的删除操作。
考虑满足什么条件的连续子段可以消除: 块白色, 块黑色。也就是 块砖之中只有一块黑色或有 块白色。于是考虑维护一个前缀和数组,记录前缀白色砖或黑色砖的块数(我的代码实现中是记录的黑色砖个数)。
整理一下,在删除的时候需要满足以下几个条件:
- 是连续段。
- 恰有 块黑色砖(或恰有 块白色砖)。
于是这个题做完了。
代码实现
#include <bits/stdc++.h> #define loop(i,a,b) for(int i=(a);i<=(int)(b);i++) #define rloop(i,a,b) for(int i=(a);i>=(int)(b);i--) using namespace std; typedef long long ll; const int N=1e6+5; const int mod=1e9+7; const int inf=0x3f3f3f3f; int n,k,sum[N]; char c; stack<int>st,ans; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n>>k; loop(i,1,n){ cin>>c; st.push(i); int s=st.size(); sum[s]=sum[s-1]+(int)(c=='c'); if(s>=k+1&&sum[s]-sum[s-k-1]==1){ rloop(j,s,s-k)ans.push(st.top()),st.pop(); } } int T=0; while(!ans.empty()){ cout<<ans.top()<<' '; ans.pop(); T=(T+1)%(k+1); if(!T)cout<<'\n'; } return 0; }完结撒花花!
- 1
信息
- ID
- 5081
- 时间
- 1000ms
- 内存
- 264MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者