题解:P13983 数列分块入门 8
Defy_HeavenS · · 题解
#6284. 数列分块入门 8 - 题目 - LibreOJ
题面
给出一个长为
技巧
设一个标记
时间复杂度。设块长为
注:这题可以用珂朵莉树做。
代码
#include<bits/stdc++.h>
#define umap unordered_map
#define uset unordered_set
#define mset multiset
#define yes cout<<"Yes\n"
#define no cout<<"No\n"
#define fi first
#define se second
#define pb push_back
#define mkp make_pair
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define tmax(a,b) (a)=max((a),(b))
#define tmin(a,b) (a)=min((a),(b))
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=5e5+5,M=555;
const LL Inf=1e18;
int n,a[N],T,tot,be[M],en[M],bel[N];
LL tag[M];
void init(){
T=tot=sqrt(n);
for(int i=1;i<=tot;i++){
be[i]=en[i-1]+1,en[i]=i*T;
}
en[tot]=n;
for(int i=1;i<=tot;i++){
tag[i]=Inf;
for(int j=be[i];j<=en[i];j++){
bel[j]=i;
}
}
}
int cover(int l,int r,int val){
int res=0;
if(tag[bel[l]]==Inf){
for(int i=l;i<=r;i++){
if(a[i]==val) res++;
a[i]=val;
}
}else if(tag[bel[l]]==val){
res=r-l+1;
}else{
for(int i=be[bel[l]];i<=en[bel[r]];i++){
if(l<=i&&i<=r) a[i]=val;
else a[i]=tag[bel[l]];
}
tag[bel[l]]=Inf;
}
return res;
}
int work(int l,int r,int val){
if(bel[l]==bel[r]){
return cover(l,r,val);
}
int res=cover(l,en[bel[l]],val)+cover(be[bel[r]],r,val);
for(int i=bel[l]+1;i<=bel[r]-1;i++){
if(tag[i]==Inf){
for(int j=be[i];j<=en[i];j++){
if(a[j]==val) res++;
}
}else if(tag[i]==val){
res+=en[i]-be[i]+1;
}
tag[i]=val;
}
return res;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
init();
for(int i=1,l,r,c;i<=n;i++){
cin>>l>>r>>c;
cout<<work(l,r,c)<<"\n";
}
return 0;
}
拓展
如果修改和查询操作分开呢?就无法均摊了。这就是 Paint The Wall - HDU 4391。
设
这里空间不够用,就把
const int N=1e5+5,M=320;
int n,m,a[N],T,tot,be[M],en[M],bel[N],tag[M];
map<int,int>col[M];
void init(){
T=tot=sqrt(n);
for(int i=1;i<=tot;i++){
be[i]=en[i-1]+1,en[i]=i*T;
}
en[tot]=n;
for(int i=1;i<=tot;i++){
tag[i]=-1;
for(int j=be[i];j<=en[i];j++){
bel[j]=i,col[i][a[j]]++;
}
}
}
void pushdown(int bel){
if(tag[bel]==-1) return;
for(int i=be[bel];i<=en[bel];i++){
a[i]=tag[bel];
}
tag[bel]=-1;
}
void cover(int l,int r,int val){
if(~tag[bel[l]]) pushdown(bel[l]);
for(int i=l;i<=r;i++){
col[bel[l]][a[i]]--,a[i]=val,col[bel[l]][a[i]]++;
}
}
int get(int l,int r,int val){
if(~tag[bel[l]]) pushdown(bel[l]);
int res=0;
for(int i=l;i<=r;i++){
if(a[i]==val){
res++;
}
}
return res;
}
void update(int l,int r,int val){
if(bel[l]==bel[r]){
cover(l,r,val);
return;
}
cover(l,en[bel[l]],val),cover(be[bel[r]],r,val);
for(int i=bel[l]+1;i<=bel[r]-1;i++){
col[i].clear();
col[i][val]=en[i]-be[i]+1;
tag[i]=val;
}
}
LL query(int l,int r,int val){
if(bel[l]==bel[r]){
return get(l,r,val);
}
LL res=get(l,en[bel[l]],val)+get(be[bel[r]],r,val);
for(int i=bel[l]+1;i<=bel[r]-1;i++){
if(col[i].find(val)!=col[i].end()) res+=col[i][val];
}
return res;
}
signed main(){
while(cin>>n>>m){
for(int i=1;i<=n;i++){
cin>>a[i];
}
init();
for(int i=1,op,l,r,z;i<=m;i++){
cin>>op>>l>>r>>z;
l++,r++;
if(op==1){
update(l,r,z);
}else{
cout<<query(l,r,z)<<"\n";
}
}
for(int i=1;i<=tot;i++){
col[i].clear();
}
}
return 0;
}