题意
给出一个数列,一种操作是修改某个数,另一种是提问一个位置区间
[
l
,
r
]
[l,r]
[l,r] 和颜色区间
[
x
,
y
]
[x,y]
[x,y]
问,若把连续相同的数字看做一个的话,在区间
[
l
,
r
]
[l,r]
[l,r] 中只考虑数字介于
[
x
,
y
]
[x,y]
[x,y] 的话,有几个
题解
一段连续相同的数字,将第一个看做本身,其余的看做 0, 问题就成了,在区间
[
l
,
r
]
[l,r]
[l,r] 内,数字范围在
[
x
,
y
]
[x,y]
[x,y]的个数
如果没有修改的话,就是一个主席树的模板题了,有修改,就是带修主席树的模板题了
代码
#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-7
#define pi 3.141592653589793
#define mod 998244353
// #define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// uniform_real_distribution<double> dis(-1.0,1.0);
int a[N],b[N];
int q[N],ql[N],qr[N],qk[N];
int rt[N],tot,n,m,cnt;
struct PST{
int ls[N*200],rs[N*200],sum[N*200],p[2],w[2][20][20],cnt,t;
void init(int Max){cnt=0;tot=Max;}
void ins(int &i,int x,int val,int l=1,int r=tot){
if (!i) i=++cnt; sum[i]+=val;
if (l==r) return; int mid=l+r>>1;
if (x<=mid) ins(ls[i],x,val,l,mid);
else ins(rs[i],x,val,mid+1,r);
}
inline void Modify(int pos,int val){
for(int i=pos;i<=n;i+=i&-i) ins(rt[i],a[pos],val);
}
int ask(int x,int y,int d,int l=1,int r=tot){
int v=d+1;
if (l==x&&y==r){
int s=0; for(int i=1;i<=t;i++) s+=sum[w[1][d][i]],s-=sum[w[0][d][i]];
return s;
}
int mid=l+r>>1;
if (y<=mid) {
for(int i=1;i<=t;i++) w[0][v][i]=ls[w[0][d][i]],w[1][v][i]=ls[w[1][d][i]];
return ask(x,y,v,l,mid);
}else
if (x>mid) {
for(int i=1;i<=t;i++) w[0][v][i]=rs[w[0][d][i]],w[1][v][i]=rs[w[1][d][i]];
return ask(x,y,v,mid+1,r);
}else{
for(int i=1;i<=t;i++) w[0][v][i]=ls[w[0][d][i]],w[1][v][i]=ls[w[1][d][i]];
int t1=ask(x,mid,v,l,mid);
for(int i=1;i<=t;i++) w[0][v][i]=rs[w[0][d][i]],w[1][v][i]=rs[w[1][d][i]];
int t2=ask(mid+1,y,v,mid+1,r);
return t1+t2;
}
}
inline int query(int l,int r,int x,int y){
p[0]=p[1]=0;memset(w,0,sizeof w);
for(int i=l-1;i;i-=i&-i) w[0][0][++p[0]]=rt[i];
for(int i=r;i;i-=i&-i) w[1][0][++p[1]]=rt[i];
t=max(p[0],p[1]);
return ask(x,y,0);
}
}PST;
namespace IO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void print(char *s){while (*s)out(*s++);}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void print(char *s){Ostream.print(s);}
};
using namespace IO;
int main()
{
read(n);read(m);
for(int i=1;i<=n;i++) read(b[i]);
for(int i=1;i<=n;i++) a[i]=b[i]==b[i-1]?0:b[i];
PST.init(n);
for(int i=1;i<=n;i++) if (a[i]) PST.Modify(i,1);
while(m--){
int op,l,r,x,y;
read(op);
if(op==2){
read(l);read(r); read(x);read(y);
print(PST.query(l,r,x,y)+(b[l]>=x&&b[l]<=y&&a[l]==0));
Ostream.out('\n');
}else{
read(l);read(r);
if(b[l]==r) continue;
if (b[l+1]==b[l]){
PST.Modify(l+1,-1); a[l+1]=b[l+1]; PST.Modify(l+1,1);
}
if(a[l]) PST.Modify(l,-1);
b[l]=r; a[l]=b[l]==b[l-1]?0:b[l];
if (a[l]) PST.Modify(l,1);
if (b[l+1]==b[l]){
PST.Modify(l+1,-1); a[l+1]=0;
}
}
}
return 0;
}