整理的算法模板合集: ACM模板
题目传送门
碎块必须每次都遍历一遍,整块打标记
这里开始我们O(n)遍历一遍打标记,当一个整块被打满标记以后(会变成相同的数字),就是O(1)查询,均摊时间复杂度为 O ( s q r t ( n ) ) O(sqrt(n)) O(sqrt(n))
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 500007, M = 1000007, INF = 0x3f3f3f3f;
int n, m;
int block, bi[N];
int tag[N];
int v[N];
ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
void reset(int x)
{
if(tag[x] == -1)return ;
for(int i = (x - 1) * block + 1; i <= x * block; ++ i)
v[i] = tag[x];
tag[x] = -1;
}
int solve(int a, int b, int c)
{
int ans = 0;
reset(bi[a]);
for(int i = a; i <= min(bi[a] * block, b); ++ i){
if(v[i] == c)
ans ++ ;
v[i] = c;
}
if(bi[a] != bi[b]){
reset(bi[b]);
for(int i = (bi[b] - 1) * block + 1; i <= b; ++ i){
if(v[i] == c)
ans ++ ;
v[i] = c;
}
}
for(int i = bi[a] + 1; i <= bi[b] - 1; ++ i){
if(tag[i] != -1){
if(tag[i] == c){
ans += block;
}
tag[i] = c;
}
else {
for(int j = (i - 1) * block + 1; j <= i * block; ++ j){
if(v[j] == c)
ans ++ ;
v[j] = c;
}
tag[i] = c;
}
}
return ans;
}
int main()
{
memset(tag, -1, sizeof tag);
n = read();
block = sqrt(n);
for(int i = 1; i <= n; ++ i)
v[i] = read();
for(int i = 1; i <= n; ++ i){
bi[i] = (i - 1) / block + 1;
}
for(int i = 1; i <= n; ++ i){
int a = read(), b = read(), c = read();
printf("%d\n", solve(a, b, c));
}
return 0;
}