1. 程式人生 > 實用技巧 >JZOJ 6801. NOIP2020.9.19模擬patrick

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\n" , 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);
		}
	}
}