zoukankan      html  css  js  c++  java
  • HDU 4348(主席树 标记永久化)

    题面一看就是裸的数据结构题,而且一看就知道是主席树。。。

    一共四种操作:1:把区间[l, r]的数都加上d,并且更新时间。2:查询当前时间的区间和。3:查询历史时间的区间和。4:时光倒流到某个时间。

    正常来说,主席树比较难支持区间操作,但是我们可以用标记永久化的方法去实现区间操作。标记永久化和懒标记下放不一样,标记永久化是这样操作的:对所有和标记区间相关的区间,直接加上这次操作的影响,如果这个区间被标记区间完全覆盖,就打上标记。查询的时候,需要把访问沿途的所有的区间的标记算上。

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 100010;
    struct SegementTree {
    	int ls, rs;
    	long long sum, flag;
    };
    SegementTree tr[maxn * 200];
    int tot, a[maxn], root[maxn], Time;
    void pushup(int now) {
    	tr[now].sum = tr[tr[now].ls].sum + tr[tr[now].rs].sum;
    }
    void build(int now, int l, int r) {
    	tr[now].ls = tr[now].rs = tr[now].sum = tr[now].flag = 0;
    	if(l == r) {
    		tr[now].sum = a[l];
    		tr[now].flag = 0;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	tr[now].ls = ++tot; build(tot, l, mid);
    	tr[now].rs = ++tot; build(tot, mid + 1, r);
    	pushup(now);
    }
    void insert(int lnow, int rnow, int l, int r, int ql, int qr, LL val) {
    	tr[rnow] = tr[lnow];tr[rnow].sum += val * (qr - ql + 1);
    	if(l == ql && r == qr) {
    		tr[rnow].flag += val;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if(qr <= mid) {
    		tr[rnow].ls = ++tot; insert(tr[lnow].ls, tot, l, mid, ql, qr, val);
    	} else if(ql > mid) {
    		tr[rnow].rs = ++tot; insert(tr[lnow].rs, tot, mid + 1, r, ql, qr, val);
    	} else {
    		tr[rnow].ls = ++tot; insert(tr[lnow].ls, tot, l, mid, ql, mid, val);
    		tr[rnow].rs = ++tot; insert(tr[lnow].rs, tot, mid + 1, r, mid + 1, qr, val);
    	}
    //	pushup(rnow);
    }
    LL query(int now, int l, int r, int ql ,int qr) {
    	if(l >= ql && r <= qr) {
    		return tr[now].sum;
    	}
    	int mid = (l + r) >> 1;
    	LL ans = tr[now].flag * (qr - ql + 1);
    	if(qr <= mid) ans += query(tr[now].ls, l, mid, ql, qr);
    	else if(ql > mid) ans += query(tr[now].rs, mid + 1, r, ql, qr);
    	else {
    		ans += query(tr[now].ls, l, mid, ql, mid);
    		ans += query(tr[now].rs, mid + 1, r, mid + 1, qr);
    	}
    	return ans;
    }
    char s[10];
    int main() {
    	int x, y, z, n, m, kase = 0;
    	while(~scanf("%d%d", &n, &m)) {
    		tot = 0, Time = 0;
    		kase++;
    		if(kase > 1) printf("
    ");
    		for (int i = 1; i <= n; i++) {
    			scanf("%d", &a[i]);
    		}
    		root[0] = ++tot;
    		build(tot, 1, n);
    		while(m--) {
    			scanf("%s", s + 1);
    			if(s[1] == 'C') {
    				scanf("%d%d%d", &x, &y, &z);
    				root[++Time] = ++tot;
    				insert(root[Time - 1], root[Time], 1, n, x, y, z);
    			} else if(s[1] == 'Q') {
    				scanf("%d%d", &x, &y);
    				printf("%lld
    ", query(root[Time], 1, n, x, y));
    			} else if(s[1] == 'H') {
    				scanf("%d%d%d", &x, &y, &z);
    				printf("%lld
    ", query(root[z], 1, n, x, y));
    			} else {
    				scanf("%d", &x);
    				tot = root[x + 1] - 1;
    				Time = x;
    			}
    		}
    	}
    }
    

      

  • 相关阅读:
    steam
    node 循序渐进
    node 常用指令 node 扩展链接
    window 常用指令
    web API
    SHAREPOINT
    div设置边框黑框显示
    sharepoint更新多行文本webparth
    sharepoint读取启用了追加功能的多行文本的历史版本记录
    JS实现多附件上传(asp.net)
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10606107.html
Copyright © 2011-2022 走看看