区队模拟赛 - 0621

T1

首先可以发现一种特殊的,可以让复杂度爆炸的数据:在数字前面有许多的前导0,那么我们可以先预处理一遍,在过程中跳跃

其次,发现\(0\le l[i] \le r[i] \le 1e5\),即查询的上界非常小,最多只有6位数字,桶数组记录

所以,对于任意起点\(i\),可以先预处理后面第一个非零位置,然后枚举出cnt

最后是区间查询,直接使用前缀和即可

#include<bits/stdc++.h>
using namespace std;

signed main()
{
 	ios::sync_with_stdio(0);cin.tie(0);
 	int n,m;
 	cin>>n>>m;
 	string s;
 	cin>>s;
 	vector<int> nxt(n + 1,n);
 	for(int i = n - 1;i >= 0;i--)
 	{
 		if(s[i] != '0') nxt[i] = i;
 		else nxt[i] = nxt[i + 1];
	 }const int N = 1e6+5;
	vector<long long> cnt(N);
	for(int i = 0;i<n;i++)
	{
		cnt[0] += nxt[i] - i;
		int x = 0;
		for(int j = nxt[i];j < min(n,nxt[i] + 6); j++)
		{
			x = x * 10 + (s[j] -'0');
			cnt[x]++;
		}
	}
	for(int i =1;i<N;i++)
	{
		cnt[i] += cnt[i - 1];
	}
	while(m--)
	{
		int l,r;
		cin>>l>>r;
		cout<<cnt[r] - (l?cnt[l - 1] : 0) << '\n';
	}
	return 0;
}



T2

首先观察到数据范围十分的小-->\(n \le 20\),所以就考虑使用二进制来标识错误集合

然后把每个错误集合当作一个点,补丁就是建边条件

接着隐式建边==>每个点枚举下补丁即可

掩码对应

b1:必须包含的错误集合。条件为 (u & b1) == b1

2 b2:必须不包含的错误集合。条件为 (u & b2) == 0

3 f 1:修复的错误集合。操作为去掉这些 1:u - (u & f1)

4 f 2:引入的错误集合。操作为增加这些 1:| f2

将每个二进制状态视作图中的一个顶点,将每一个满足条件的补丁视作一条有向边,
边的权重就是补丁的耗时。

Code:


posted @ 2026-09-08 13:21  Zhenggeek  阅读(4)  评论(0)    收藏  举报