题目大意
动态维护数列中大于等于某个数的极长连续段的个数。
解题思路
(Code)
#include<cstdio>
using namespace std;
long long f[2000005],a[500005],tag[2000005],ans,n,m;
void pushdown(int l,int r,int k)
{
if (!tag[k]) return;
int mid = l + r >> 1;
tag[k << 1] += tag[k];
tag[k << 1 | 1] += tag[k];
f[k << 1] += tag[k] * (mid - l + 1);
f[k << 1 | 1] += tag[k] * (r - mid);
tag[k] = 0;
}
void change(int l,int r,int k,int L,int R,int u)
{
if (r < L && l > R) return;
if (l >= L && r <= R)
{
f[k] += u * (r - l + 1);
tag[k] += u;
return;
}
pushdown(l,r,k);
int mid = l + r >> 1;
if (L <= mid) change(l,mid,k << 1,L,R,u);
if (R > mid) change(mid + 1,r,k << 1 | 1,L,R,u);
f[k] = f[k << 1] + f[k << 1 | 1];
}
int query(int l,int r,int k,int u)
{
if (l == r && l == u) return f[k];
pushdown(l,r,k);
int mid = l + r >> 1;
if (u <= mid) return query(l,mid,k << 1,u);
else return query(mid + 1,r,k << 1 | 1,u);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
if (a[i] > 500000) a[i] = 500000;
if (a[i] > a[i - 1]) change(1,500000,1,a[i - 1] + 1,a[i],1);
}
char s[5];
int lst = 0;
for (int i = 1; i <= m; i++)
{
int q,p;
scanf("%s",s);
if (s[0] == 'Q')
{
scanf("%d",&q);
q = q ^ lst;
lst = query(1,500000,1,q);
printf("%d
",lst);
}
else
{
scanf("%d%d",&q,&p);
q = q ^ lst,p = p ^ lst;
if (a[q] < a[q + 1]) change(1,500000,1,a[q] + 1,a[q + 1],-1);
if (p < a[q + 1]) change(1,500000,1,p + 1,a[q + 1],1);
if (a[q] > a[q - 1]) change(1,500000,1,a[q - 1] + 1,a[q],-1);
if (p > a[q - 1]) change(1,500000,1,a[q - 1] + 1,p,1);
a[q] = p;
}
}
}