題意
給出一個數列,一種操作是修改某個數,另一種是提問一個位置區間 和顏色區間
問,若把連續相同的數字看做一個的話,在區間 中只考慮數字介於 的話,有幾個
題解
一段連續相同的數字,將第一個看做本身,其餘的看做 0, 問題就成了,在區間 內,數字範圍在 的個數
離線CDQ分治
顯然一個詢問可以轉化爲4個
其實就是一個三維偏序問題,因爲有修改,所以時間是一維,因爲要詢問區間小於某個數的個數,所以位置是第二維,數值是第三維
代碼
#include<bits/stdc++.h>
#define N 800110
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi 3.141592653589793
#define mod 1000000007
#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))
#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;
struct node{
int b,c,w,id;
}q[N],tmp[N];
int ans[N],d[N],n,m,a[N];
inline void up(int x,int p){for (;x<=n;x+=x&-x) d[x]+=p;}
inline int sum(int x){int t=0;for (;x;x-=x&-x) t+=d[x]; return t;}
void CDQ(int l,int r){
if (l==r) return;
int t=l+r>>1,x=l,y=t+1,k=l;
CDQ(l,t);
CDQ(t+1,r);
while(x<=t && y<=r){
if (q[x].b<=q[y].b){
if (!q[x].id) up(q[x].c,q[x].w);
tmp[k++]=q[x++];
} else {
if (q[y].id) ans[q[y].id]+=sum(q[y].c)*q[y].w;
tmp[k++]=q[y++];
}
}
while(y<=r){
if (q[y].id) ans[q[y].id]+=sum(q[y].c)*q[y].w;
tmp[k++]=q[y++];
}
for (int i=l;i<x;i++) if (!q[i].id) up(q[i].c,-q[i].w);
while(x<=t) tmp[k++]=q[x++];
for (int i=l;i<=r;i++) q[i]=tmp[i];
}
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(int argc, char const *argv[]){
read(n); read(m);
int cnt=0;
for(int i=1;i<=n;i++) {
read(a[i]);
if (a[i]!=a[i-1]) q[++cnt]={i,a[i],1,0};
}
int tot=0;
for(int i=1;i<=m;i++){
int op,l,r,x,y;
read(op); read(l); read(r);
if (op==2){
read(x); read(y);
tot++;
q[++cnt]={r,y,1,tot};
q[++cnt]={l-1,y,-1,tot};
q[++cnt]={r,x-1,-1,tot};
q[++cnt]={l-1,x-1,1,tot};
ans[tot]=a[l]>=x&&a[l]<=y&&a[l]==a[l-1];
}else{
if (a[l]==r) continue;
if (a[l+1]==a[l]) q[++cnt]={l+1,a[l+1],1,0};
if (a[l]!=a[l-1]) q[++cnt]={l,a[l],-1,0};
a[l]=r;
if (a[l]!=a[l-1]) q[++cnt]={l,a[l],1,0};
if (a[l]==a[l+1]) q[++cnt]={l+1,a[l+1],-1,0};
}
}
CDQ(1,cnt);
for(int i=1;i<=tot;i++) print(ans[i]),Ostream.out('\n');
return 0;
}