P13983 数列分块入门 8
区间查询等于
就是这个“同时”,太厉害了。
我好像只会一个
正解是,对于每个块,我们维护块内的数是否相同,如果不同,我们暴力统计,如果相同我们直接判断。
这样为什么能保证时间复杂度呢。因为一个块查询的次数
所以总的时间复杂度是
#include<bits/stdc++.h>
using namespace std;
const int N =3e5+10;
#define int long long
int l[N],r[N],pos[N],lzy[N],n,tot,a[N];
void Devide(){
int len=sqrt(n),tot=n/len;
if(len*len!=n) tot++;
for(int i=1;i<=tot;i++) l[i]=(i-1)*len+1,r[i]=l[i]+len-1;
r[tot]=n;
for(int i=1;i<=tot;i++){
bool f=true; int lst=a[l[i]];
for(int j=l[i];j<=r[i];j++){
pos[j]=i; if(a[j]!=lst) f=false;
}
if(f==false) lzy[i]=LLONG_MAX;
else lzy[i]=lst;
}
}
void update(int L,int R,int c){
bool f=true;
if(pos[L]==pos[R]){
for(int i=L;i<=R;i++) a[i]=c;
for(int i=l[pos[L]];i<=r[pos[L]];i++) if(a[i]!=c) f=false;
if(f) lzy[pos[L]]=c; else lzy[pos[L]]=LLONG_MAX;
return ;
}
for(int i=L;i<=r[pos[L]];i++) a[i]=c;
f=true;
for(int i=l[pos[L]];i<=r[pos[L]];i++) if(a[i]!=c) f=false;
if(f) lzy[pos[L]]=c; else lzy[pos[L]]=LLONG_MAX;
for(int i=l[pos[R]];i<=R;i++) a[i]=c;
f=true;
for(int i=l[pos[R]];i<=r[pos[R]];i++) if(a[i]!=c) f=false;
if(f) lzy[pos[R]]=c; else lzy[pos[R]]=LLONG_MAX;
for(int i=pos[L]+1;i<=pos[R]-1;i++) lzy[i]=c;
}
int Query(int L,int R,int c){
int Num=0;
if(pos[L]==pos[R]){
if(lzy[pos[L]]!=LLONG_MAX){
for(int i=l[pos[L]];i<=r[pos[L]];i++) a[i]=lzy[pos[L]];
}
for(int i=L;i<=R;i++) if(a[i]==c) Num++;
return Num;
}
if(lzy[pos[L]]!=LLONG_MAX){
for(int i=l[pos[L]];i<=r[pos[L]];i++) a[i]=lzy[pos[L]];
}
for(int i=L;i<=r[pos[L]];i++) if(a[i]==c) Num++;
if(lzy[pos[R]]!=LLONG_MAX){
for(int i=l[pos[R]];i<=r[pos[R]];i++) a[i]=lzy[pos[R]];
}
for(int i=l[pos[R]];i<=R;i++) if(a[i]==c) Num++;
for(int i=pos[L]+1;i<=pos[R]-1;i++){
if(lzy[i]==LLONG_MAX){
for(int j=l[i];j<=r[i];j++) if(a[j]==c) Num++;
}
else{
if(lzy[i]==c) Num+=(r[i]-l[i]+1);
}
}
return Num;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
Devide();
for(int i=1,L,R,c;i<=n;i++){
cin>>L>>R>>c;
cout<<Query(L,R,c)<<endl;
update(L,R,c);
}
return 0;
}