【GMOJ6801】模拟patrick

题目

题目链接:https://gmoj.net/senior/#main/show/6801
给出一个长度为 (n) 的数列,支持单点修改,整体查询超过 (h) 的数字连成的区间个数。

思路

建立权值树状数组,第一棵的第 (i) 个位置表示有数列中多少数字等于 (i);第二棵第 (i) 个位置表示数列中有多少位置 (j) 满足 (min(a_j,a_{j+1})=i)
对于一次询问 (h),答案即为 ((n-bit1.query(h-1))-(n-1-bit2.query(h-1)))
(=bit1.query(h-1)-bit2.query(h-1)+1)
时间复杂度 (O(nlog n))

代码

#include <bits/stdc++.h>
using namespace std;

const int N=500010;
int n,m,last,a[N];
char type[3];

struct BIT
{
	int c[N];
	
	void add(int x,int v)
	{
		for (int i=x;i<N;i+=i&-i)
			c[i]+=v;
	}
	
	int query(int x)
	{
		int sum=0;
		for (int i=x;i;i-=i&-i)
			sum+=c[i];
		return sum;
	}
}bit1,bit2;

int main()
{
	freopen("patrick.in","r",stdin);
	freopen("patrick.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		bit1.add(a[i],1);
		if (i>1) bit2.add(min(a[i],a[i-1]),1);
	}
	while (m--)
	{
		scanf("%s",type);
		if (type[0]=='Q')
		{
			int h;
			scanf("%d",&h); h^=last;
			last=bit2.query(h-1)-bit1.query(h-1)+1;
			printf("%d
",last);
		}
		else
		{
			int x,h;
			scanf("%d%d",&x,&h); x^=last; h^=last;
			bit1.add(a[x],-1);
			if (x>1) bit2.add(min(a[x],a[x-1]),-1);
			if (x<n) bit2.add(min(a[x],a[x+1]),-1);
			a[x]=h;
			bit1.add(a[x],1);
			if (x>1) bit2.add(min(a[x],a[x-1]),1);
			if (x<n) bit2.add(min(a[x],a[x+1]),1);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/stoorz/p/13827666.html