JZOJ 6801. NOIP2020.9.19模拟patrick

题目大意

动态维护数列中大于等于某个数的极长连续段的个数。

思路

我们考虑每段的开头,记为 (i),高度为 (a_i)
那么此时水淹的高度必然满足 (a_{i-1} < x leq a_i)
这样的 (x) 在此处会给答案贡献加一
那么我们考虑所有的这种位置,开一棵权值线段树,对于这些 (x) 的位置都加 (1)
询问时就单点查询 (x) 在线段树种的值就行了
修改时注意它原来的贡献,包括它与前面的数和它与后面的数
这些减去,修改后在加上新的贡献
然后,就没有然后了······

(Code)

#include<cstdio>
#define ls (k << 1)
#define rs (ls | 1)
using namespace std;

const int N = 5e5;
int n , m , a[N + 5] , last;
struct seg{
	int sum , tag;
}t[4 * N + 5];

void pushdown(int k , int l , int r)
{
	if (!t[k].tag) return;
	int m = (l + r) >> 1;
	t[ls].sum += (m - l + 1) * t[k].tag , t[ls].tag += t[k].tag;
	t[rs].sum += (r - m) * t[k].tag , t[rs].tag += t[k].tag;
	t[k].tag = 0;
}

void pushup(int k){t[k].sum = t[ls].sum + t[rs].sum;}

void update(int l , int r , int k , int x , int y , int v)
{
	if (x <= l && r <= y)
	{
		t[k].sum += (r - l + 1) * v;
		t[k].tag += v;
		return;
	}
	pushdown(k , l , r);
	int mid = (l + r) >> 1;
	if (x <= mid) update(l , mid , ls , x , y , v);
	if (y > mid) update(mid + 1 , r , rs , x , y , v);
	pushup(k);
}

int query(int l , int r , int k , int x)
{
	if (l == r && l == x) return t[k].sum;
	pushdown(k , l , r);
	int mid = (l + r) >> 1;
	if (x <= mid) return query(l , mid , ls , x);
	else return query(mid + 1 , r , rs , x);
}

int main()
{
	freopen("patrick.in" , "r" , stdin);
	freopen("patrick.out" , "w" , stdout);
	scanf("%d%d" , &n , &m);
	for(register int i = 1; i <= n; i++)
	{
		scanf("%d" , a + i);
		if (a[i] > N) a[i] = N;
		if (a[i] > a[i - 1]) update(1 , N , 1 , a[i - 1] + 1 , a[i] , 1);
	}
	char opt[5]; int x , y;
	for(register int i = 1; i <= m; i++)
	{
		scanf("%s" , opt);
		if (opt[0] == 'Q')
		{
			scanf("%d" , &x) , x ^= last;
			last = query(1 , N , 1 , x);
			printf("%d
" , last);
		}
		else {
			scanf("%d%d" , &x , &y) , x ^= last , y ^= last;
			if (a[x] > a[x - 1]) update(1 , N , 1 , a[x - 1] + 1 , a[x] , -1);
			if (a[x + 1] > a[x]) update(1 , N , 1 , a[x] + 1 , a[x + 1] , -1);
			a[x] = y;
			if (a[x] > a[x - 1]) update(1 , N , 1 , a[x - 1] + 1 , a[x] , 1);
			if (a[x + 1] > a[x]) update(1 , N , 1 , a[x] + 1 , a[x + 1] , 1);
		}
	}
}
原文地址:https://www.cnblogs.com/leiyuanze/p/13696226.html