zoukankan      html  css  js  c++  java
  • 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);
    		}
    	}
    }
    
  • 相关阅读:
    【tarjan】【树的直径】【CF】K. Königsberg Bridges
    【组合数学】【恒等式】简单和、交错和
    【组合数学】【恒等式】$sum_{k=0}^{r}C_m^k imes C_{n}^{r-k}=C_{m+n}^r$
    【组合数学】【恒等式】$C_{n}^{r} imes C_{n-r}^{k-r}=C_{n}^{k} imes C_k^{r}$
    【树形DP】D. Serval and Rooted Tree
    【图论】图的欧拉定理
    【图论】网络流解决二分图最大匹配量问题
    【计算几何】atan2函数
    【单峰计数DP】Problem F – Fabricating Sculptures
    Java基础之:自定义泛型
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13696226.html
Copyright © 2011-2022 走看看