1. 程式人生 > >【樹狀陣列套線段樹】數列

【樹狀陣列套線段樹】數列

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for (int i = a;i <= b;i ++)

using namespace std;

const int maxn = 120005;
const int lim = 120000;
const int low = -100000;
const int high = 60000;
const int maxm = 7000005;
int A[maxn],left[maxm],right[maxm],tree[maxm];
int root[maxn];
int N,Q,tot;

inline void Insert(int &z,int l,int r,int p)
{
	if (!z) z = ++ tot;
	if (l == r)
	{
		tree[z] ++;
		return;
	}
	int mid = (l + r) >> 1;
	if (p <= mid) Insert(left[z],l,mid,p);
	else Insert(right[z],mid+1,r,p);
	tree[z] = tree[left[z]] + tree[right[z]];
}

inline int lowbit(int x)
{
	return (x & (-x));
}

void Ins(int x,int y)
{
	while (x <= lim)
	{
		Insert(root[x],low,high,y);
		x += lowbit(x);
	}
}

inline int Query(int z,int l,int r,int x,int y)
{
	if (!z) return 0;
	if (x <= l && r <= y) return tree[z];
	int ret = 0;
	int mid = (l + r) >> 1;
	if (x <= mid) ret += Query(left[z],l,mid,x,y);
	if (y > mid) ret += Query(right[z],mid+1,r,x,y);
	return ret;
}

int Que(int x,int l,int r)
{
	int ret = 0;
	l = max(l,low);
	r = min(r,high);
	while (x)
	{
		ret += Query(root[x],low,high,l,r);
		x -= lowbit(x);
	}
	return ret;
}

int main()
{
	scanf("%d%d",&N,&Q);
	fo(i,1,N) scanf("%d",&A[i]);
	fo(i,1,N) Ins(i+A[i],i-A[i]);
	fo(cas,1,Q)
	{
		char op[10];
		int x,k;
		scanf("%s",op);
		scanf("%d%d",&x,&k);
		if (op[0] == 'Q')
		{
			int ans = Que(min(x+A[x]+k,lim),x-A[x]-k,x-A[x]+k) - Que(max(min(x+A[x]-k-1,lim),0),x-A[x]-k,x-A[x]+k);
			printf("%d\n",ans);
		} else
		{
			A[x] = k;
			Ins(x+A[x],x-A[x]);
		}
	}
	return 0;
}