• 无聊的数列


    题目

    sol:
    线段树维护等差数列。lazy_tag维护首项和公差。pushdown时将首项和公差累加到子节点上去。应重新计算右节点的首项。

    #include <iostream>
    
    #include <cstring>
    
    #include <cstdio>
    
    
    
    using namespace std;
    
    
    
    const int N = 1e5 + 100;
    
    
    
    struct Tree {
    
    	int l, r;
    
    	int v, fir, d;
    
    } tr[N << 2];
    
    
    
    int n, m;
    
    int a[N];
    
    
    
    
    
    void build(int u, int l, int r) {
    
    	tr[u].l = l, tr[u].r = r;
    
    	if( l == r)	{
    
    		tr[u].v = a[l]; 
    
    		return;
    
    	}
    
    	int mid = tr[u].l + tr[u].r >> 1;
    
    	build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    
    }
    
    
    
    void pushdown(int u) {
    
    	if( tr[u].fir || tr[u].d) {
    
    		Tree & ls = tr[u << 1], &rs = tr[u << 1 | 1];
    
    		ls.fir += tr[u].fir;
    
    		ls.d += tr[u].d;
    
    		ls.v += tr[u].fir;
    
    		int first = tr[u].fir + (ls.r - ls.l + 1) * tr[u].d;//右侧的首项 
    
    		rs.fir += first;
    
    		rs.d += tr[u].d;
    
    		rs.v += first;
    
    		tr[u].d = 0;
    
    		tr[u].fir = 0;
    
    	}
    
    }
    
    
    
    void change(int u, int l, int r, int k, int d) {
    
    	if( tr[u].l >= l && tr[u].r <= r) {
    
    		int first = k + (tr[u].l - l) * d;
    
    		tr[u].fir += first;
    
    		tr[u].d += d;
    
    		tr[u].v += first;
    
    		return;
    
    	}
    
    	pushdown(u);
    
    	int mid = tr[u].l + tr[u].r >> 1;
    
    	if( l <= mid)	change(u << 1, l, r, k, d);
    
    	if( r > mid)	change(u << 1 | 1, l, r, k, d);
    
    }
    
    
    
    int query(int u, int k) {
    
    	if( tr[u].l == tr[u].r)	{
    
    		return tr[u].v;
    
    	}
    
    	pushdown(u);
    
    	int mid = tr[u].l + tr[u].r >> 1;
    
    	if( k <= mid)	
    
    	    return query(u << 1, k);
    
    	else 
    
    	    return query(u << 1 | 1, k);
    
    }
    
    
    
    int main()
    
    {
    
    //	freopen("E:\data.in.txt", "r", stdin);
    
    //	freopen("E:\data.out.txt", "w", stdout);
    
    	scanf("%d%d", &n, &m);
    
    	for(int i = 1; i <= n; i ++) {
    
    		scanf("%d", &a[i]); 
    
    	}
    
    	build(1, 1, n);
    
    	while(m --) {
    
    		int opt, l, r, k, d;
    
    		scanf("%d", &opt);
    
    		if( opt == 1) {
    
    			scanf("%d%d%d%d", &l, &r, &k, &d);
    
    			change(1, l, r, k, d);
    
    		}
    
    		else {
    
    			scanf("%d", &k);
    
    			printf("%d
    ", query(1, k));
    
    		}
    
    	}
    
    	return 0;
    
    } 
    
  • 相关阅读:
    后缀自动机学习笔记
    [bzoj4516][Sdoi2016]生成魔咒——后缀自动机
    [bzoj1692][Usaco2007 Dec]队列变换——贪心+后缀数组
    BZOJ4811 [Ynoi2017]由乃的OJ
    codeforces796E Exam Cheating
    BZOJ1004 [HNOI2008]Cards
    BZOJ1798 [Ahoi2009]Seq 维护序列seq
    BZOJ4785 [Zjoi2017]树状数组
    UOJ207 共价大爷游长沙
    POJ3768 Katu Puzzle
  • 原文地址:https://www.cnblogs.com/wyy0804/p/13768539.html
Copyright © 2020-2023  润新知