I. Yukino With Subinterval
题目链接:
Problem Descripe
Yukino has an array (a_1, a_2 cdots a_n). As a tsundere girl, Yukino is fond of studying subinterval.
Today, she gives you four integers $l, r, x, y $, and she is looking for how many different subintervals ([L, R]) are in the interval ([l, r])that meet the following restraints:
- (a_L =a_{L+1} =cdots=a_R), and for any $ iin [L,R], x le a_i le y$.
- The length of such a subinterval should be maximum under the first restraint.
Note that two subintervals ([L_1,R_1] , [L_2,R_2]) are different if and only if at least one of the following formulas is true:
- (L1 cancel= L2)
- (R1 cancel= R2)
Yukino, at the same time, likes making tricks. She will choose two integers (pos,v), and she will change (a_{pos}) to (v).
Now, you need to handle the following types of queries:
- (1 pos v) : change (a_{pos}) to $v $
- (2) (l r x y): print the number of legal subintervals in the interval ([l, r])
Input
The first line of the input contains two integers (n, m (1 le n, m le 2 imes 10^5))– the numbers of the array and the numbers of queries respectively.
The second line of the input contains nnn integers (a_i (1 le a_i le n)).
For the next mmm line, each containing a query in one of the following queries:
- (1) (pos) (v (1 le pos, v le n)): change (a_{pos}) to (v)
- (2 l r x y (1 le l le r le n) (1 le x le y le n)): print the number of legal subintervals in the interval ([l,r])
Output
For each query of the second type, you should output the number of legal subintervals in the interval ([l, r]).
样例输入
6 3
3 3 1 5 6 5
2 2 3 4 5
1 3 2
2 1 6 1 5
样例输出
0
4
样例解释
For the first operations, there are (3) different subintervals (([2, 2],[3, 3],[2,3]))in the interval ([2, 3]), but none of them meets all the restraints.
For the third operations, the legal subintervals in interval ([1, 6]) are: ([1, 2], [3, 3], [4, 4], [6, 6])
Notes that although subintervals ([1,1]) and ([2,2]) also meet the first restraint, we can extend them to subinterval ([1, 2]). So the length of them is not long enough, which against the second one.
题意
给你一个序列,提供两种操作
- (1) (pos) (v (1 le pos, v le n)): 将 (a_{pos}) 改为 (v)
- (2 l r x y (1 le l le r le n) (1 le x le y le n)): 输出([l,r]) 中权值(in [x,y]) 的个数。特别注意一段连续相同的数只算一次
题解
树套树(n)年前打的,早就忘了,于是直接跳过,其实这就是一道可修改区间第k大
模板题吧,如果不会的可以去luogu
学习一下。
模板传送门:https://www.luogu.org/problem/P3380
这题唯一要解决的就是怎么处理连续段只算一次的问题了。我是树状数组套线段树,于是如果(a[i]=a[i-1])那么就不处理。
还有几个需要注意的地方
- 如果改变了(a[i])的值,记得更改(a[i-1])和(a[i+1])
- 对于区间([l,r]),记得特判(a[l]),可能(a[l]=a[l-1]),但是这时也要算
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x7f7f7f7f
#define N 200050
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
int n,m,treeNode;
int a[N],ql[20],qr[20];
struct Tree{int ls,rs,sum;}tr[N*150];
void update(int&x,int p,int tt,int l,int r)
{
if (x==0)x=++treeNode;
tr[x].sum+=tt;
if (l==r)return;
int mid=(l+r)>>1;
if (p<=mid)update(tr[x].ls,p,tt,l,mid);
else update(tr[x].rs,p,tt,mid+1,r);
}
void change(int x,int p,int tt)
{while(x<=n)update(x,p,tt,1,n+1),x+=x&-x;}
void getRt(int l,int r)
{
ql[0]=qr[0]=0;
while(l)ql[++ql[0]]=l,l-=l&-l;
while(r)qr[++qr[0]]=r,r-=r&-r;
}
int getSum()
{
int ans=0;
for(int i=1;i<=ql[0];i++)ans-=tr[tr[ql[i]].ls].sum;
for(int i=1;i<=qr[0];i++)ans+=tr[tr[qr[i]].ls].sum;
return ans;
}
void move_L()
{
for(int i=1;i<=ql[0];i++)ql[i]=tr[ql[i]].ls;
for(int i=1;i<=qr[0];i++)qr[i]=tr[qr[i]].ls;
}
void move_R()
{
for(int i=1;i<=ql[0];i++)ql[i]=tr[ql[i]].rs;
for(int i=1;i<=qr[0];i++)qr[i]=tr[qr[i]].rs;
}
int _Rank(int p,int l,int r)
{
if (l==r)return 0;
int mid=(l+r)>>1,tp=getSum();
if (p<mid){move_L();return _Rank(p,l,mid);}
move_R(); return tp+_Rank(p,mid+1,r);
}
int Rank(int l,int r,int k)
{
getRt(l-1,r);
return _Rank(k-1,1,n+1);
}
void work()
{
int id,pos,v,l,r,x,y;
read(n); read(m);
treeNode=n;
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1;i<=n;i++)if (a[i]!=a[i-1])change(i,a[i],1);
for(int i=1;i<=m;i++)
{
read(id);
if (id==1)
{
read(pos); read(v);
if (a[pos]!=a[pos-1])change(pos,a[pos],-1);
if (v!=a[pos-1])change(pos,v,1);
if (a[pos]==a[pos+1])change(pos+1,a[pos+1],1);
if (v==a[pos+1])change(pos+1,a[pos+1],-1);
a[pos]=v;
}
if (id==2)
{
read(l); read(r); read(x); read(y);
int ans=-Rank(l,r,x)+Rank(l,r,y+1);
if (a[l]==a[l-1]&&x<=a[l]&&a[l]<=y)ans++;
printf("%d
",ans);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
work();
}