感觉已经优化完了。
已优化的点:
#include<bits/stdc++.h>
using namespace std;
namespace fast_IO {
#define IOSIZE 100000
char ibuf[IOSIZE], obuf[IOSIZE], *p1 = ibuf, *p2 = ibuf, *p3 = obuf;
#define getchar() ((p1==p2)and(p2=(p1=ibuf)+fread(ibuf,1,IOSIZE,stdin),p1==p2)?(EOF):(*p1++))
#define putchar(x) ((p3==obuf+IOSIZE)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
#define isdigit(ch) (ch>47&&ch<58)
#define isspace(ch) (ch<33)
template<typename T> inline T read() { T s = 0; int w = 1; char ch; while (ch = getchar(), !isdigit(ch) and (ch != EOF)) if (ch == '-') w = -1; if (ch == EOF) return false; while (isdigit(ch)) s = s * 10 + ch - 48, ch = getchar(); return s * w; }
template<typename T> inline bool read(T &s) { s = 0; int w = 1; char ch; while (ch = getchar(), !isdigit(ch) and (ch != EOF)) if (ch == '-') w = -1; if (ch == EOF) return false; while (isdigit(ch)) s = s * 10 + ch - 48, ch = getchar(); return s *= w, true; }
template<typename T> inline void print(T x) { if (x < 0) putchar('-'), x = -x; if (x > 9) print(x / 10); putchar(x % 10 + 48); }
inline bool read(char &s) { while (s = getchar(), isspace(s)); return true; }
inline bool read(char *s) { char ch; while (ch = getchar(), isspace(ch)); if (ch == EOF) return false; while (!isspace(ch)) *s++ = ch, ch = getchar(); *s = '\000'; return true; }
inline void print(char x) { putchar(x); }
inline void print(char *x) { while (*x) putchar(*x++); }
inline void print(const char *x) { for (int i = 0; x[i]; i++) putchar(x[i]); }
inline bool read(std::string& s) { s = ""; char ch; while (ch = getchar(), isspace(ch)); if (ch == EOF) return false; while (!isspace(ch)) s += ch, ch = getchar(); return true; }
inline void print(std::string x) { for (int i = 0, n = x.size(); i < n; i++) putchar(x[i]); }
inline bool read(bool &b) { char ch; while(ch=getchar(), isspace(ch)); b=ch^48; return true; }
inline void print(bool b) { putchar(b+48); }
template<typename T, typename... T1> inline int read(T& a, T1&... other) { return read(a) + read(other...); }
template<typename T, typename... T1> inline void print(T a, T1... other) { print(a), print(other...); }
struct Fast_IO { ~Fast_IO() { fwrite(obuf, p3 - obuf, 1, stdout); } } io;
template<typename T> Fast_IO& operator >> (Fast_IO &io, T &b) { return read(b), io; }
template<typename T> Fast_IO& operator << (Fast_IO &io, T b) { return print(b), io; }
#define cout io
#define cin io
#define endl '\n'
} using namespace fast_IO;
const int N=8e5+10;
const int M=1e5+10;
struct node {
int op,time;
int a,b;short type;
}e[N];
int n,pre[N],m,res[M],lst[N];
int del[M];
bitset<M> has;
unordered_map<int,int> uni;
int tim;
namespace BIT {
int t[M];
inline int lowbit(int x) {return x&-x;}
inline void update(int x,int val) {
while (x<=n) {
t[x]+=val;
x+=lowbit(x);
}
return ;
}
inline int query(int x) {
int ans=0;
while (x) {
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
}using namespace BIT;
namespace Chotholly_Willem {
struct Chotholly {
int l,r;
mutable int val;
bool operator <(const Chotholly &x) const {return l<x.l;}
};
set<Chotholly> s,se[N];
inline auto Insert(int l,int r,int val) {
se[val].insert({l,r,val});
return s.insert({l,r,val}).first;
}
inline void Delete(int l,int r,int val) {
s.erase({l,r,val});
se[val].erase({l,r,val});
return ;
}
inline auto split(int pos) {
auto it=s.lower_bound({pos,0,0});
if (it!=s.end() and it->l==pos) return it;
it--;
if (it->r<pos) return s.end();
int l=it->l,r=it->r,val=it->val;
Delete(l,r,val);
Insert(l,pos-1,val);
return Insert(pos,r,val);
}
inline int Pre(int pos) {
auto it=--s.upper_bound({pos,0,0});
if (it->l<pos) return pos-1;
else {
auto itl=se[it->val].lower_bound({pos,0,0});
if (itl!=se[it->val].begin()) return (--itl)->r;
return 0;
}
}
inline void assign(int l,int r,int val,int time) {
auto itr=split(r+1),itl=split(l);
int len=0;
for (auto it=itl;it!=itr;it++) {
if (it!=itl) del[++len]=it->l;
auto itt=se[it->val].upper_bound(*it);
if (itt!=se[it->val].end()) del[++len]=itt->l;
auto dele=it;
se[it->val].erase(*dele);
}
del[++len]=l;
s.erase(itl,itr);
Insert(l,r,val);
auto itt=se[val].upper_bound({l,r,val});
if (itt!=se[val].end()) del[++len]=itt->l;
for (int i=1;i<=len;i++) {
e[++m].op=0,e[m].a=del[i],e[m].b=pre[del[i]],e[m].time=time,e[m].type=-1;
pre[del[i]]=Pre(del[i]);
e[++m].op=0,e[m].a=del[i],e[m].b=pre[del[i]],e[m].time=time,e[m].type=1;
}
return ;
}
}using namespace Chotholly_Willem;
inline void CDQ(int l,int r) {
if (l==r) return ;
int mid=l+r>>1,p=l,q=mid+1,len=0;
CDQ(l,mid),CDQ(mid+1,r);
// while (p<=mid and q<=r) {
// if (e[p].b<e[q].b) {
// if (e[p].op==0) {
// update(e[p].a,e[p].type);
// }
// tmp[++len]=e[p++];
// }
// else {
// if (e[q].op==1) {
// res[e[q].time]+=e[q].type*query(e[q].a);
// }
// tmp[++len]=e[q++];
// }
// }
// while (p<=mid) {
// if (e[p].op==0) {
// update(e[p].a,e[p].type);
// }
// tmp[++len]=e[p++];
// }
// while (q<=r) {
// if (e[q].op==1) {
// res[e[q].time]+=e[q].type*query(e[q].a);
// }
// tmp[++len]=e[q++];
// }
sort(e+l,e+mid+1,[](node x,node y){return x.b==y.b?x.a<y.a:x.b<y.b;});
sort(e+mid+1,e+r+1,[](node x,node y){return x.b==y.b?x.a<y.a:x.b<y.b;});
int j=l;
for (int i=mid+1;i<=r;i++) {
while (j<=mid and e[j].b<e[i].b) {
if (e[j].op==0) {
update(e[j].a,e[j].type);
}
j++;
}
if (e[i].op==1) {
res[e[i].time]+=e[i].type*query(e[i].a);
}
}
for (int i=l;i<j;i++) {
if (e[i].op==0) {
update(e[i].a,-e[i].type);
}
}
return ;
}
signed main() {
int _;
cin>>n>>_;
for (int i=1;i<=n;i++) {
int x;cin>>x;
if (!uni[x]) uni[x]=++tim;
x=uni[x];pre[i]=lst[x];lst[x]=i;
e[++m].op=0,e[m].time=0,e[m].a=i,e[m].b=pre[i],e[m].type=1;
Insert(i,i,x);
}
for (int i=1;i<=_;i++) {
char op;cin>>op;
int l,r,val;
if (op=='2') has[i]=1;
if (op=='2') {
cin>>l>>r;
e[++m].op=1,e[m].time=i,e[m].a=l-1,e[m].b=l,e[m].type=-1;
e[++m].op=1,e[m].time=i,e[m].a=r,e[m].b=l,e[m].type=1;
}
else if (op=='1') {
cin>>l>>r>>val;
if (!uni[val]) uni[val]=++tim;
val=uni[val];
assign(l,r,val,i);
// e[++m].op=0,e[m].time=i,e[m].a=l,e[m].b=Pre(val[l],l),e[m].type=-1,e[m].idx=++cnt;
// e[++m].op=0,e[m].time=i,e[m].a=l,e[m].b=Pre(r,l),e[m].type=1,e[m].idx=++cnt;
// if (Nex(val[l],l)) {
// int next=Nex(val[l],l);
// e[++m].op=0,e[m].time=i,e[m].a=next,e[m].b=Pre(val[next],next),e[m].type=-1,e[m].idx=++cnt;
// e[++m].op=0,e[m].time=i,e[m].a=next,e[m].b=Pre(val[l],l),e[m].type=1,e[m].idx=++cnt;
// }
// if (Nex(r,l-1)) {
// int next=Nex(r,l-1);
// e[++m].op=0,e[m].time=i,e[m].a=next,e[m].b=Pre(val[next],next),e[m].type=-1,e[m].idx=++cnt;
// e[++m].op=0,e[m].time=i,e[m].a=next,e[m].b=l,e[m].type=1,e[m].idx=++cnt;
// }
// se[val[l]].erase(l),se[r].insert(l);
// val[l]=r;
}
}
// sort(e+1,e+m+1,[](node x,node y){return x.idx<y.idx;});
CDQ(1,m);
for (int i=1;i<=_;i++) {
if (has[i]) {
cout<<res[i]<<endl;
}
}
return (0-0);
}