区队模拟赛 - 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:

浙公网安备 33010602011771号