题目描述
给出一个长为 nn 的数列,以及 nn 个操作,操作涉及区间询问等于一个数 cc 的元素,并将这个区间的所有元素改为 cc。
输入格式
第一行输入一个数字 nn。
第二行输入 nn 个数字,第 i 个数字为 a_iai,以空格隔开。
接下来输入 nn 行询问,每行输入三个数字 ll、rr、cc,以空格隔开。
表示先查询位于 [l,r][l,r] 的数字有多少个是 cc,再把位于 [l,r][l,r] 的数字都改为 cc。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
Inputcopy | Outputcopy |
---|---|
4 1 2 2 4 1 3 1 1 4 4 1 2 2 1 4 2 | 1 1 0 2 |
数据范围与提示
对于 100\%100% 的数据,1 \leq n \leq 100000, -2^{31} \leq \mathrm{others}1≤n≤100000,−231≤others、\mathrm{ans} \leq 2^{31}-1ans≤231−1。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 500010;
ll a[MAXN],block[MAXN],sum[2000],num[2000];
int st[2000],ed[2000],n,s,lazy[2000];
void init()
{
s = (int)sqrt(n);
int cnt = 0;
for(int i = 1;i <= n; i += s){
st[++cnt] = i;ed[cnt] = min(i+s-1,n);
}
for(int i = 1;i <= cnt; i++){
for(int j = st[i];j <= ed[i]; j++)
block[j] = i;
num[i] = 0x3f3f3f3f;
}
}
void pushdown(int x)
{
if(lazy[x]){
for(int i = st[x];i <= ed[x]; i++)
a[i] = num[x];
num[x] = 0x3f3f3f3f;
lazy[x] = 0;
}
}
int query(int x,int y,int c)
{
int l = block[x],r = block[y],ans = 0;
if(l == r){
pushdown(block[x]);
for(int i = x;i <= y; i++){
if(a[i] == c) ans++;
else a[i] = c;
}
}
else{
pushdown(block[x]);pushdown(block[y]);
for(int i = x;i <= ed[l]; i++){
if(a[i] == c) ans++;
else a[i] = c;
}
for(int i = st[r];i <= y; i++){
if(a[i] == c) ans++;
else a[i] = c;
}
for(int i = l+1;i < r; i++){
if(lazy[i]){
if(num[i] == c) ans += s;
else num[i] = c;
}
else {
for(int j = st[i];j <= ed[i]; j++){
if(a[j] == c) ans++;
else a[j] = c;
}
lazy[i] = 1;
num[i] = c;
}
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin >> n;
init();
for(int i = 1;i <= n; i++){
cin >> a[i];
}
int l,c,r;
for(int i = 1;i <= n; i++){
cin >> l >> r >> c;
cout << query(l,r,c) << "\n";
}
return 0;
}