D. Tokitsukaze and Meeting(滑动窗口)

Problem - D - Codeforces

 丰风正在安排会议。会议室里有n排m列的座位。正好有n个学生参加会议,包括几个调皮的学生和几个认真的学生。学生被从1到n数点。学生将按顺序进入会场。当第i位同学进入会场时,他将坐在第1排的第1列,已经入座的同学将向后移动一个座位。具体来说,坐在第i行第j (1 SjS m-1)列的学生将移动到第i行第(j+1)列的学生,坐在第i行第m列的学生将移动到第(i +1)行第1列的学生。

题解:
我们要分别计算好的行列,对于行来说我们可以把它看作是一个长度为m的滑动窗口,

对于i >= m

f[i] = f[i-m]

只用判断i前长度为m的一段是否含1即可

相当于现在A位置新进来一个学生,看B上面的一行是否有1

对于判断列,我们可以发现,如果某一列标记过了,那么就不会变,所以我们每次遍历到的列没有标记并且s[i] = 1,并且++

 

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define int long long
const int N = 4e6 + 10;
typedef pair<int, int> PII;
string s;
int c[N];
int f[N];
int sum[N];
void solve() 
{
	int n,m;
	cin >>n >> m;
	cin >> s;
	s = " " + s;

	for(int i = 1;i <= n*m;i++)
	{
		sum[i] = sum[i - 1] + (s[i] - '0');
	}
	for(int i = 1;i <= n*m;i++)
	{
		if(i >= m)
		f[i] = f[i - m];
		f[i] += (sum[i] - sum[max(0ll,i-m)] > 0);
	}
	int now = 1;
	int cnt = 0;
	for(int i = 1;i <= n*m;i++)
	{
		if(c[now] == 0&&s[i] == '1')
		{
			c[now] = 1;
			++cnt;
		}
		cout << cnt + f[i] <<" ";
		now ++;
		if(now == m + 1)
		now = 1;
	}
	cout << "\n";
	for(int i = 1;i <= n*m;i++)
	{
		c[i] = 0;
		sum[i] = 0;
		f[i] = 0;
	}
}


signed main() 
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
//scanf("%lld",&t);
	while (t--) 
	{
		solve();
	}
}
//3 F
//5 B
//6 F
//9 F
//10 B
//12 F
//15 FB
//18 FB

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值