I. Yukino With Subinterval
题意:有两种操作,第一种修改一个位置的值,第二种求给定区间[l,r]内有多少合法区间。合法区间定义:al = al+1 = … = ar ,且该区间为最长。
题解:如果这题不带修改,主席树就写完了。那么带修改动态开点线段树套树状数组。
注意:这题卡常,需要快读。
#include<bits/stdc++.h>
#define m (l+r)/2
#define low(x) x&-x
using namespace std;
const int maxn = 2e5+10;
int n,q;
int cnt,cnz,V[22];
int rt[maxn],a[maxn],sum[maxn*210],ls[maxn*210],rs[maxn*210];
void up(int l,int r,int k,int v)
{
for(int i=1;i<=cnz;i++)
sum[V[i]] += v;
if(l==r) return ;
if(k>m){
for(int i=1;i<=cnz;i++){
if(!rs[V[i]]) rs[V[i]] = ++cnt;
V[i] = rs[V[i]];
}
up(m+1,r,k,v);
}
else {
for(int i=1;i<=cnz;i++)
{
if(!ls[V[i]]) ls[V[i]] = ++cnt;
V[i] = ls[V[i]];
}
up(l,m,k,v);
}
}
int qu(int l,int r,int ql,int qr)
{
if(ql<=l&&qr>=r)
{
int ans = 0;
for(int i=1;i<=cnz;i++)
ans += sum[V[i]];
return ans;
}
int ans = 0,V2[22];
if(ql<=m)
{
for(int i=1;i<=cnz;i++)
V2[i] = V[i] , V[i] = ls[V[i]];
ans += qu(l,m,ql,qr);
for(int i=1;i<=cnz;i++)
V[i] = V2[i];
}
if(qr>m)
{
for(int i=1;i<=cnz;i++)
V[i] = rs[V[i]];
ans += qu(m+1,r,ql,qr);
}
return ans ;
}
void modify(int x,int k,int v)
{
cnz = 0;
for(;x<=n;x+=low(x))
V[++cnz] = rt[x];
up(1,n,k,v);
}
int query(int x,int ql,int qr)
{
cnz = 0;
for(;x>0;x-=low(x))
V[++cnz] = rt[x];
return qu(1,n,ql,qr);
}
#define reads(n) FastIO::read(n)
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
int read(char *s) {
while (bn) {
for (; bi < bn && buf[bi] <= ' '; bi++);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
int sn = 0;
while (bn) {
for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
s[sn] = 0;
return sn;
}
bool read(int& x) {
int n = read(str), bf;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf < 0) x = -x;
return 1;
}
};
int main()
{
FastIO::read(n);FastIO::read(q);
for(int i=1;i<=n;i++)
rt[i] = ++cnt;
for(int i=1;i<=n;i++)
{
reads(a[i]);
// scanf("%d",&a[i]);
if(a[i]!=a[i-1])
modify(i,a[i],1);
}
int op,l,r,x,y;
for(int i=1;i<=q;i++)
{
reads(op);
// scanf("%d",&op);
if(op==1)
{
reads(l);reads(r);
// scanf("%d%d",&l,&r);
if(a[l]==r) continue;
if(a[l-1]!=a[l]) {
modify(l,a[l],-1);
if(r!=a[l-1]) modify(l,r,1);
}
if(a[l-1]==a[l]){
modify(l,r,1);
}
if(a[l]==a[l+1]){
modify(l+1,a[l+1],1);
}
else if(a[l+1]==r){
modify(l+1,a[l+1],-1);
}
a[l] = r;
}
else {
reads(l);reads(r);reads(x);reads(y);
// scanf("%d%d%d%d",&l,&r,&x,&y);
int ans = query(rt[r],x,y) - query(rt[l-1],x,y);
if(a[l]==a[l-1]&&a[l]>=x&&a[l]<=y) ans ++;
printf("%d\n",ans);
}
}
}