zoukankan      html  css  js  c++  java
  • [模板][线段树]

     1.区间加和求极值lazy

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    typedef long long ll;
    const ll MOD = 1e9 + 7;
    const int MX = 1e5 + 7;
    
    int arr[MAXN] = {0};
    
    struct sgt
    {
    	struct node{int l, r, mx, add;}t[MAXN << 2];
    	
    	void pushup(int now)
    	{
    		t[now].mx = max(t[now * 2].mx, t[now * 2 + 1].mx);
    	}
    	
    	void build(int now, int l, int r)
    	{
    		t[now].l = l, t[now].r = r;
    		if(l == r) {t[now].mx = arr[l]; return ;}
    		int mid = (l + r) / 2;
    		build(now * 2, l, mid);
    		build(now * 2 + 1, mid + 1, r);
    		pushup(now);
    	}
    	
    	void push(int now)
    	{
    		if(t[now].add)
    		{
    			int val = t[now].add;
    			t[now * 2].mx += val;
    			t[now * 2 + 1].mx += val;
    			t[now * 2].add += val;
    			t[now * 2 + 1].add += val;
    			t[now].add = 0;
    		}
    	}
    	void add(int now, int l, int r, int val)
    	{
    		if(l <= t[now].l && r >= t[now].r)
    		{
    			t[now].add += val;
    			t[now].mx += val;
    			return ;
    		}
    		push(now);
    		int mid = (t[now].l + t[now].r) / 2;
    		if(l <= mid) add(now * 2, l, r, val);
    		if(r > mid) add(now * 2 + 1, l, r, val);
    		t[now].mx = max(t[now * 2].mx, t[now * 2 + 1].mx);
    	}
    	int query(int now, int l, int r)
    	{
    		if(l <= t[now].l && r >= t[now].r) return t[now].mx;
    		push(now);
    		int ret = 0, mid = (t[now].l + t[now].r) / 2;
    		if(l <= mid) ret = max(ret, query(now * 2, l, r));
    		if(r > mid) ret = max(ret, query(now * 2 + 1, l, r));
    		return ret;
    	}
    };
    
    int main()
    { 
    	//ios::sync_with_stdio(0);
    	//cin.tie(0); cout.tie(0);
    	//freopen("1.txt", "r", stdin);
    	
    	int n, m;
    	
    	cin >> n >> m;
    	
    	for(int i = 1; i <= n; ++i)
    		cin >> arr[i];
    		
    	sgt T;
    	
    	T.build(1, 1, n);
    		
    	char q;
    	int x, y, z;
    	while(m--)
    	{
    		cin >> q;
    		if(q == 'Q')
    		{
    			cin >> x >> y;
    			cout << T.query(1, x, y) << '
    ';
    		}
    		else
    		{
    			cin >> x >> y >> z;
    			T.add(1, x, y, z);
    		}
    	}
    
        return 0;
    }
    
    struct sgt
    {
    	struct node{int l, r, mx, mi, add;}t[MAXN << 2];
    	
    	sgt()	{ memset(t, 0, sizeof(node)); }
    	void pushup(int now)
    	{
    		t[now].mx = max(t[now * 2].mx, t[now * 2 + 1].mx);
    		t[now].mi = min(t[now * 2].mi, t[now * 2 + 1].mi);
    	}
    	
    	void build(int now, int l, int r)
    	{
    		t[now].l = l, t[now].r = r;
    		if(l == r) {t[now].mx = t[now].mi = 0; return ;}
    		int mid = (l + r) / 2;
    		build(now * 2, l, mid);
    		build(now * 2 + 1, mid + 1, r);
    		pushup(now);
    	}
    	
    	void push(int now)
    	{
    		if(t[now].add)
    		{
    			int val = t[now].add;
    			t[now * 2].mx += val;
    			t[now * 2 + 1].mx += val;
    			t[now * 2].mi += val;
    			t[now * 2 + 1].mi += val;
    			t[now * 2].add += val;
    			t[now * 2 + 1].add += val;
    			t[now].add = 0;
    		}
    	}
    	
    	void add(int now, int l, int r, int val)
    	{
    		if(l <= t[now].l && r >= t[now].r)
    		{
    			t[now].add += val;
    			t[now].mx += val;
    			t[now].mi += val;
    			return ;
    		}
    		push(now);
    		int mid = (t[now].l + t[now].r) / 2;
    		if(l <= mid) add(now * 2, l, r, val);
    		if(r > mid) add(now * 2 + 1, l, r, val);
    		t[now].mx = max(t[now * 2].mx, t[now * 2 + 1].mx);
    		t[now].mi = min(t[now * 2].mi, t[now * 2 + 1].mi);
    	}
    	
    	int query(int now, int l, int r)
    	{
    		if(l <= t[now].l && r >= t[now].r) return t[now].mx;
    		push(now);
    		int ret = -INF, mid = (t[now].l + t[now].r) / 2;
    		if(l <= mid) ret = max(ret, query(now * 2, l, r));
    		if(r > mid) ret = max(ret, query(now * 2 + 1, l, r));
    		return ret;
    	}
    	
    	int querymi(int now, int l, int r)
    	{
    		if(l <= t[now].l && r >= t[now].r) return t[now].mi;
    		push(now);
    		int ret = 0x3f3f3f3f, mid = (t[now].l + t[now].r) / 2;
    		if(l <= mid) ret = min(ret, querymi(now * 2, l, r));
    		if(r > mid) ret = min(ret, querymi(now * 2 + 1, l, r));
    		return ret;
    	}
    }t;

     2.区间加和求和lazy

    #pragma GCC optimize(2)
    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    #include <cctype>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <ctime>
    #include <vector>
    #include <fstream>
    #include <list>
    #include <iomanip>
    #include <numeric>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1e6 + 10;
    
    ll arr[MAXN] = {0};
    ll tree[MAXN * 4 + 10] = {0};
    ll b[MAXN] = {0};
    
    void init(int now, int l, int r)
    {
    	if(l == r) { tree[now] = arr[l]; return ; }
    	int mid = l + (r - l) / 2;
    	init(now * 2, l, mid);
    	init(now * 2 + 1, mid + 1, r);
    	tree[now] = tree[now * 2] + tree[now * 2 + 1];
    }
    
    void pushdown(int now, int l , int r)
    {
    	if(b[now])
    	{
    		b[now * 2] += b[now];
    		b[now * 2 + 1] += b[now];
    		int mid = l + (r - l) / 2;
    		tree[now * 2] += b[now] * (mid - l + 1);
    		tree[now * 2 + 1] += b[now] * (r - mid);
    		b[now] = 0; 
    	}
    }
    
    ll find(int now, int l, int r, int x, int y)
    {
    	if(x > r || y < l) return 0;
    	if(x <= l && y >= r) return tree[now]; 
    	pushdown(now, l, r);
    	int mid = l + (r - l) / 2;
    	ll ans = 0;
    	ans += find(now * 2, l, mid, x, y);
    	ans += find(now * 2 + 1, mid + 1, r, x, y);
    	return ans;
    }
    
    
    
    void update(int now, int l, int r, int x, int y, ll add)
    {	
    	if(l > y || x > r) return ;
    		
    	if(l >= x && r <= y) b[now] += add, tree[now] += add * (r - l + 1); return ;
    	pushdown(now, l, r);
    	int mid = l + (r - l) / 2;	
    	update(now * 2, l, mid, x, y, add);
    	update(now * 2 + 1, mid + 1, r, x , y, add);
    	tree[now] = tree[now * 2] + tree[now * 2 + 1];
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);     cout.tie(0);
    
        ll len, oprt;
        cin>>len>>oprt;
        for(int i = 1; i <= len; i++) cin>>arr[i];
        init(1, 1, len);
    	int x, y;
    	while(oprt--)
    	{
    		int mode, x, y, k;
    		cin>>mode;
    		if(mode == 1)
    		{
    			cin>>x>>y>>k;
    			update(1, 1, len, x, y, k);
    		}
    		else
    		{
    			cin>>x>>y;
    			cout<<find(1, 1, len, x, y)<<endl;
    		}
    	}
        return 0;
    }
    

    2. 区间乘

    //#pragma GCC optimize(2)
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <cctype>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <ctime>
    #include <vector>
    #include <fstream>
    #include <list>
    #include <iomanip>
    #include <numeric>
    using namespace std;
    typedef long long ll;
      
    const int MAXN = 4e4 + 10;
     
    ll arr[MAXN];
     
    struct node             //节点
    {
        ll v;
        ll mul, add;     //lazatag
    }tree[MAXN];
    
    void init(int now, int fst, int lst) //建树
    {
        tree[now].mul = 1, tree[now].add = 0;
        if(fst == lst) { tree[now].v = arr[fst]; return ; }
        int mid = (fst + lst) / 2;
        init(now * 2, fst, mid);
        init(now * 2 + 1, mid + 1, lst);   
        tree[now].v = tree[now * 2].v + tree[now * 2 + 1].v;
    }
    
    void pushdown(int now, int fst, int lst) //lazypush
    {
        int mid = (fst + lst) / 2;
        tree[now * 2].v = (tree[now * 2].v * tree[now].mul + tree[now].add * (mid - fst + 1));
        tree[now * 2 + 1].v = (tree[now * 2 + 1].v * tree[now].mul + tree[now].add * (lst - mid));
        tree[now * 2].mul = (tree[now * 2].mul * tree[now].mul);
        tree[now * 2 + 1].mul = (tree[now * 2 + 1].mul * tree[now].mul);
        tree[now * 2].add = (tree[now * 2].add * tree[now].mul + tree[now].add);
        tree[now * 2 + 1].add = (tree[now * 2 + 1].add * tree[now].mul + tree[now].add);
        tree[now].mul = 1;
        tree[now].add = 0;
    }
    
    void updatemul(int now, int x, int y, int fst, int lst, long long k)
    {
    
        if(lst < x || y < fst)
            return ;
        if(fst <= x && y <= lst)
        {
            tree[now].v = (tree[now].v * k);
            tree[now].mul = (tree[now].mul * k);
            tree[now].add = (tree[now].add * k);
        }
        else
        {
            pushdown(now, x, y);
            int mid = (x + y) / 2;
            updatemul(now * 2, x, mid, fst, lst, k);
            updatemul(now * 2 + 1, mid + 1, y, fst, lst, k);
            tree[now].v = (tree[now * 2].v + tree[now * 2 + 1].v);
        }
    }
    
    void updatesum(int now, int x, int y, int l, int r, long long k)
    {
         
        if(r < x || y < l)
            return ;
        if(l <= x && y <= r)
        {
            tree[now].add = (tree[now].add + k);
            tree[now].v = (tree[now].v + k * (y-x+1));
        }
        else
        {
            pushdown(now, x, y);
            int mid = (x + y) / 2;
            updatesum(now * 2, x, mid, l, r, k);
            updatesum(now * 2 + 1, mid + 1, y, l, r, k);
            tree[now].v = (tree[now * 2].v + tree[now * 2 + 1].v);
        }
    }
    
    long long query(int now, int x, int y, int fst, int lst) //询问所有数和
    {
        if(lst < x || y < fst)
            return 0;
        if(fst <= x && y <= lst)
        {
            return tree[now].v;
        }
        pushdown(now, x, y);
        int mid = (x + y) / 2;
        return (query(now * 2, x, mid, fst, lst) + query(now * 2 + 1, mid + 1, y, fst, lst));
    }
     
    long long query1(int now, int x, int y, int l, int r) //询问所有数平方和
    {
        if(r < x || y < l)
            return 0;
        if(x == y) return tree[now].v * tree[now].v;
        pushdown(now, x, y);
        int m = (x + y) / 2;
        return (query1(now * 2, x, m, l, r) + query1(now * 2 + 1, m + 1, y, l, r));
    }
     
    int main()
    {
        int n, m;
     
        scanf("%d%d", &n, &m);
     
        for(int i = 1; i <= n; i++)
            scanf("%lld", &arr[i]);
     
        init(1, 1, n);
     
        while(m--)
        {
            int mode;
     
            scanf("%d", &mode);
             
            int x, y;
            long long k;
             
            if(mode == 3)
            {
                scanf("%d%d%lld", &x, &y, &k);
                updatemul(1, 1, n, x, y, k);
            }
            else if(mode == 4)
            {
                scanf("%d%d%lld", &x, &y, &k);
                updatesum(1, 1, n, x, y, k);
            }
            else if(mode == 1)
            {
                scanf("%d%d", &x, &y);
                printf("%lld
    ", query(1, 1, n, x, y));
            }
            else if(mode == 2)
            {
                cin>>x>>y;
                printf("%lld
    ", query1(1, 1, n, x, y));
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    opstack 笔记 (一) 概念
    Redis学习汇总
    MongoDB添加删除节点
    Redis主从及Cluster区别及注意事项
    叶问18
    Redis慢日志取出来
    Redis的AOF重写脚本
    使用Python比较MySQL数据库中两个数据库的表结构--转载
    关于InnoDB存储引擎 text blob 大字段的存储和优化
    MongoDB进阶之路:不仅仅是技术研究,还有优化和最佳实践--转载
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270502.html
Copyright © 2011-2022 走看看