• 线段树


    线段树模板

    struct SegmentTree {
    	int l, r;
    	int dat;
    } t[SIZE * 4]; // struct数组存储线段树
    
    void build(int p, int l, int r) {
    	t[p].l = l, t[p].r = r; // 节点p代表区间[l,r]
    	if (l == r) { t[p].dat = a[l]; return; } // 叶节点
    	int mid = (l + r) / 2; // 折半
    	build(p*2, l, mid); // 左子节点[l,mid],编号p*2
    	build(p*2+1, mid+1, r); // 右子节点[mid+1,r],编号p*2+1
    	t[p].dat = max(t[p*2].dat, t[p*2+1].dat); // 从下往上传递信息
    }
    
    build(1, 1, n); // 调用入口
    
    void change(int p, int x, int v) {
    	if (t[p].l == t[p].r) { t[p].dat = v; return; } // 找到叶节点
    	int mid = (t[p].l + t[p].r) / 2;
    	if (x <= mid) change(p*2, x, v); // x属于左半区间
    	else change(p*2+1, x, v); // x属于右半区间
    	t[p].dat = max(t[p*2].dat, t[p*2+1].dat); // 从下往上更新信息
    }
    
    change(1, x, v); // 调用入口
    
    int ask(int p, int l, int r) {
    	if (l <= t[p].l && r >= t[p].r) return t[p].dat; // 完全包含,直接返回
    	int mid = (t[p].l + t[p].r) / 2;
    	int val = 0;
    	if (l <= mid) val = max(val, ask(p*2, l, r)); // 左子节点有重叠
    	if (r > mid) val = max(val, ask(p*2+1, l, r)); // 右子节点有重叠
    	return val;
    }
    
    cout << ask(1, l, r) << endl; // 调用入口
    
    // 动态开点的线段树
    struct SegmentTree {
        int lc, rc; // 左右子节点的编号
    	int dat;
    } tr[SIZE * 2];
    int root, tot;
    
    int build() { // 新建一个节点
    	tot++;
    	tr[tot].lc = tr[tot].rc = tr[tot].dat = 0;
    	return tot;
    }
    
    // 在main函数中
    tot = 0;
    root = build(); // 根节点
    
    // 单点修改,在val位置加delta,维护区间最大值
    void insert(int p, int l, int r, int val, int delta) {
        if (l == r) {
            tr[p].dat += delta;
            return;
        }
        int mid = (l + r) >> 1; // 代表的区间[l,r]作为递归参数传递
        if (val <= mid) {
            if (!tr[p].lc) tr[p].lc = build(); // 左子树不存在,动态开点
            insert(tr[p].lc, l, mid, val, delta);
        }
        else {
            if (!tr[p].rc) tr[p].rc = build(); // 右子树不存在,动态开点
            insert(tr[p].rc, mid + 1, r, val, delta);
        }
        tr[p].dat = max(tr[tr[p].lc].dat, tr[tr[p].rc].dat);
    }
    
    // 调用
    insert(root, 1, n, val, delta);
    
    // 合并两棵线段树
    int merge(int p, int q, int l, int r) {
        if (!p) return q; // p,q之一为空
        if (!q) return p;
        if (l == r) { // 到达叶子
            tr[p].dat += tr[q].dat;
            return p;
        }
        int mid = (l + r) >> 1;
        tr[p].lc = merge(tr[p].lc, tr[q].lc, l, mid); // 递归合并左子树
        tr[p].rc = merge(tr[p].rc, tr[q].rc, mid + 1, r); // 递归合并右子树
        tr[p].dat = max(tr[tr[p].lc].dat, tr[tr[p].rc].dat); // 更新最值
        return p; // 以p为合并后的节点,相当于删除q
    }
    

    线段树维护连续的最大值和

    #include <bits/stdc++.h>
    using namespace std;
    #define P pair<int,int>
    #define ll long long
    const int N = 5e5+10;
    const int mod = 1e9+7;
    int a[N];
    struct SegmentTree{
        int l,r,dat,sum,lmax,rmax;
    }t[N*4];
    
    void build(int p,int l,int r)
    {
        t[p].l=l,t[p].r=r;
        if(t[p].l==t[p].r){t[p].dat=t[p].sum=t[p].lmax=t[p].rmax=a[l];return;}
        int mid=(l+r)/2;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].sum=t[p*2].sum+t[p*2+1].sum;
        t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax);
        t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax);
        t[p].dat=max(t[p*2].rmax+t[p*2+1].lmax,max(t[p*2].dat,t[p*2+1].dat));
    }
    void change(int p,int x,int v)
    {
        if(t[p].l==t[p].r){t[p].dat=t[p].lmax=t[p].rmax=t[p].sum=v;return;}
        int mid=(t[p].l+t[p].r)/2;
        if(x<=mid)change(p*2,x,v);
        else change(p*2+1,x,v);
        t[p].sum=t[p*2].sum+t[p*2+1].sum;
        t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax);
        t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax);
        t[p].dat=max(t[p*2].rmax+t[p*2+1].lmax,max(t[p*2].dat,t[p*2+1].dat));
    }
    SegmentTree ask(int p,int l,int r)
    {
        if(l<=t[p].l&&r>=t[p].r)
            return t[p];
        int mid=(t[p].l+t[p].r)/2,val=-(1<<30);
        SegmentTree a,b,c;
        a.dat=a.sum=a.lmax=a.rmax=val;
        b.dat=b.sum=b.lmax=b.rmax=val;
        c.sum=0;
        if(l<=mid)
        {
            a=ask(p*2,l,r);
            c.sum+=a.sum;
        }
        if(r>mid)
        {
            b=ask(p*2+1,l,r);
            c.sum+=b.sum;
        }
        c.dat=max(max(a.dat,b.dat),a.rmax+b.lmax);
        c.lmax=max(a.lmax,b.lmax+a.sum);
        if(l>mid)
            c.lmax=max(c.lmax,b.lmax);
        c.rmax=max(b.rmax,b.sum+a.rmax);
        if(r<=mid)
            c.rmax=max(c.rmax,a.rmax);
        return c;
    }
    int main()
    {
        int n,m;
        cin >> n >> m;
        for(int i=1;i<=n;i++)
        {
            cin >> a[i];
        }
        build(1,1,n);
        while(m--)
        {
            int k,x,y;
            cin >> k >> x >> y;
            if(k==1)
            {
                if(x>y)
                    swap(x,y);
                cout<<ask(1,x,y).dat<<"
    ";
            }
            if(k==2)
                change(1,x,y);
        }
    
        return 0;
    }
    
    

    线段树维护区间和

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define ll long long
    #define P pair<int,int>
    const ll INF=1e18;
    const int N=5e5+10;
    int a[N];
    struct SegmentTree{
        int l,r;
        ll sum;
    }t[N*4];
    void build(int p,int l,int r)
    {
        t[p].l = l;
        t[p].r = r;
        if(t[p].l == t[p].r){t[p].sum = a[l];return ;}
        int mid = (l+r)/2;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].sum = t[p*2].sum+t[p*2+1].sum;
    }
    void change(int p,int x,int v)
    {
        if(t[p].l == t[p].r){t[p].sum += v;return ;}
        int mid = (t[p].l+t[p].r)/2;
        if(x<=mid) change(p*2,x,v);
        else change(p*2+1,x,v);
        t[p].sum = t[p*2].sum +t[p*2+1].sum;
    }
    ll ask(int p,int l,int r)
    {
        if(l<=t[p].l&&r>=t[p].r)
            return t[p].sum;
        int mid = (t[p].l+t[p].r)/2;
        ll suml = 0,sumr = 0;
        if(l<=mid)
            suml = ask(p*2,l,r);
        if(r>mid)
            sumr = ask(p*2+1,l,r);
        return suml+sumr;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        int T,n;
        cin >> T;
        for(int kase=1;kase<=T;kase++)
        {
            cin >> n;
            for(int i=1;i<=n;i++)
            {
                cin >> a[i];
            }
            build(1,1,n);
    
    //        printf("Case %d:",kase);
            cout << "Case "<< kase << ":
    ";
            while(1)
            {
               string s;
               cin >> s;
    //           cout<<s<<"
    ";
               if(s[0]=='E')
                   break;
               else
               {
                   int x,v;
                   cin >> x >> v;
                   if(s[0]=='Q')
                       cout << ask(1,x,v) << "
    ";
                   else if(s[0]=='A')
                       change(1,x,v);
                   else if(s[0]=='S')
                       change(1,x,-v);
               }
            }
        }
        return 0;
    }
    

    线段树区间加减(延迟标记)

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define ll long long
    #define P pair<int,int>
    const ll INF=1e18;
    const int N=5e5+10;
    ll a[N];
    struct SegmentTree{
        int l,r;
        ll sum;
        ll add;
    }t[N*4];
    void build(int p,int l,int r)
    {
        t[p].l = l;
        t[p].r = r;
        t[p].add = 0;
        if(t[p].l == t[p].r){t[p].sum = a[l];return ;}
        int mid = (l+r)/2;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].sum = t[p*2].sum+t[p*2+1].sum;
    }
    void spread(int p)
    {
        if(t[p].add)
        {
            t[p*2].sum += t[p].add*(t[p*2].r-t[p*2].l+1);
            t[p*2+1].sum += t[p].add*(t[p*2+1].r-t[p*2+1].l+1);
            t[p*2].add += t[p].add;
            t[p*2+1].add += t[p].add;
            t[p].add = 0;
        }
    }
    void change(int p,int l,int r,ll v)
    {
        if(l <= t[p].l && t[p].r <= r)
        {
            t[p].sum +=(t[p].r-t[p].l+1)*v;
            t[p].add += v;
            return ;
        }
        int mid = (t[p].l+t[p].r)/2;
        spread(p);
        if(l<=mid) change(p*2,l,r,v);
        if(r>mid) change(p*2+1,l,r,v);
        t[p].sum = t[p*2].sum +t[p*2+1].sum;
    }
    ll ask(int p,int l,int r)
    {
        if(l<=t[p].l&&r>=t[p].r)
            return t[p].sum;
        int mid = (t[p].l+t[p].r)/2;
        spread(p);
        ll sum = 0;
        if(l<=mid) sum += ask(p*2,l,r);
        if(r>mid) sum += ask(p*2+1,l,r);
        return sum;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        int n,m;
        cin >> n >> m;
        for(int i=1;i<=n;i++)
        {
            cin >> a[i];
        }
        build(1,1,n);
        for(int kase=1;kase<=m;kase++)
        {
            int l,r;
            ll d;
            char flag;
            cin >> flag >> l >> r;
            if(flag=='C')
            {
                cin >> d;
                change(1,l,r,d);
            }
            else
            {
                cout << ask(1,l,r) << "
    ";
            }
        }
        return 0;
    }
    

    线段树区间修改(延迟标记)

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define ll long long
    #define P pair<int,int>
    const ll INF=1e18;
    const int N=1e5+10;
    ll a[N];
    struct SegmentTree{
        int l,r;
        ll sum;
        ll dat;
    }t[N*4];
    void build(int p,int l,int r)
    {
        t[p].l = l;
        t[p].r = r;
        t[p].dat = 0;
        if(t[p].l == t[p].r){t[p].sum = a[l];return ;}
        int mid = (l+r)/2;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].sum = t[p*2].sum+t[p*2+1].sum;
    }
    void spread(int p)
    {
        if(t[p].dat)
        {
            t[p*2].sum = t[p].dat*(t[p*2].r-t[p*2].l+1);
            t[p*2+1].sum = t[p].dat*(t[p*2+1].r-t[p*2+1].l+1);
            t[p*2].dat = t[p].dat;
            t[p*2+1].dat = t[p].dat;
            t[p].dat = 0;
        }
    }
    void change(int p,int l,int r,ll v)
    {
        if(l <= t[p].l && t[p].r <= r)
        {
            t[p].sum =(t[p].r-t[p].l+1)*v;
            t[p].dat = v;
            return ;
        }
        int mid = (t[p].l+t[p].r)/2;
        spread(p);
        if(l<=mid) change(p*2,l,r,v);
        if(r>mid) change(p*2+1,l,r,v);
        t[p].sum = t[p*2].sum +t[p*2+1].sum;
    }
    ll ask(int p,int l,int r)
    {
        if(l<=t[p].l&&r>=t[p].r)
            return t[p].sum;
        int mid = (t[p].l+t[p].r)/2;
        spread(p);
        ll sum = 0;
        if(l<=mid) sum += ask(p*2,l,r);
        if(r>mid) sum += ask(p*2+1,l,r);
        return sum;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        int n,m;
        cin >> n;
        for(int i=1;i<=n;i++)
        {
            cin >> a[i];
        }
        cin >> m;
        build(1,1,n);
        for(int kase=1;kase<=m;kase++)
        {
            int l,r;
            ll d;
            int flag;
            cin >> flag >> l >> r;
            if(flag==1)
            {
                cin >> d;
                change(1,l,r,d);
            }
            else
            {
                cout << ask(1,l,r) << "
    ";
            }
        }
        return 0;
    }
    
  • 相关阅读:
    tensorflow入门笔记(五) name_scope和variable_scope
    tensorflow入门笔记(四) tf.summary 模块
    tensorflow入门笔记(三) tf.GraphKeys
    tensorflow入门笔记(二) 滑动平均模型
    tensorflow入门笔记(一) tf.app.flags.FLAGS
    iOS友盟推送注意点
    关于gif图片重用消失问题。
    百度地图使用经验
    SQLite语句
    app登录,client和serve的常用字段。
  • 原文地址:https://www.cnblogs.com/hh13579/p/12274699.html
Copyright © 2020-2023  润新知