zoukankan      html  css  js  c++  java
  • 线段树区间乘积算法

    这是算区间乘积的算法

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    #define fori for(i=0;i<n;i++)
    #define fori1 for(i=1;i<=n;i++)
    using namespace std;
    const int maxn = 1e6 + 107;
    #define inf 0x3f3f3f3f
    const ll mod =1e9+7;
    ll p;
    struct node {
        ll l, r;//区间[l,r]
        ll add;//区间和的延时标记
        ll mul;//区间乘积的延时标记
        ll sum;//区间和
        ll ji;//区间乘积
        ll maxn; //区间最大值
        ll minn; //区间最小值
    }tree[maxn * 4 + 5];//一定要开到4倍多的空间
    
    void pushup(ll rt) {
        
        tree[rt].sum = (tree[rt << 1].sum + tree[rt << 1 | 1].sum)%p;
        tree[rt].ji = tree[rt << 1].ji * tree[rt << 1 | 1].ji;
        tree[rt].maxn = max(tree[rt << 1].maxn, tree[rt << 1 | 1].maxn);
        tree[rt].minn = min(tree[rt << 1].minn, tree[rt << 1 | 1].minn);
    }
    void pushdown(ll rt) {
        if (tree[rt].add|| tree[rt].mul != 1) {
            tree[rt << 1].ji = (tree[rt << 1].ji*(tree[rt << 1].r - tree[rt << 1].l + 1) * tree[rt].add);
            tree[rt << 1 | 1].ji *= (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * tree[rt].add;
            tree[rt << 1].sum = (tree[rt << 1].sum*tree[rt].mul+(tree[rt << 1].r - tree[rt << 1].l + 1) * tree[rt].add)%p;
            tree[rt << 1 | 1].sum = (tree[rt << 1 | 1].sum * tree[rt].mul + (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * tree[rt].add)%p;
            tree[rt << 1].maxn += tree[rt].add;
            tree[rt << 1 | 1].maxn += tree[rt].add;
            tree[rt << 1].minn += tree[rt].add;
            tree[rt << 1 | 1].minn += tree[rt].add;
            tree[rt << 1].mul = (tree[rt << 1].mul * tree[rt].mul)%p;
            tree[rt << 1 | 1].mul = (tree[rt << 1 | 1].mul*tree[rt].mul)%p;
            tree[rt << 1].add = (tree[rt<<1].add*tree[rt].mul+ tree[rt].add)%p;
            tree[rt << 1 | 1].add = (tree[rt<<1|1].add* tree[rt].mul+tree[rt].add)%p;
            tree[rt].mul = 1;
            tree[rt].add = 0;
    
        }
    }
    void build(ll l, ll r, ll rt) {
        tree[rt].l = l;
        tree[rt].r = r;
        tree[rt].add = 0;//刚开始一定要清0
        tree[rt].mul = 1;//刚开始一定要清1
        if (l == r) {
            cin>>tree[rt].sum;
            tree[rt].minn = tree[rt].maxn = tree[rt].ji=tree[rt].sum;
            return;
        }
        ll mid = (l + r) >> 1;
        build(l, mid, rt << 1);
        build(mid + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    void updata_plus(ll l, ll r, ll rt, ll val) {
        if (l <= tree[rt].l && r >= tree[rt].r) {
            tree[rt].sum = (tree[rt].sum + (tree[rt].r - tree[rt].l + 1) * val)%p;
            tree[rt].minn += val;
            tree[rt].maxn += val;
            tree[rt].add = (tree[rt].add + val)%p;//延时标记
    
            return;
        }
        pushdown(rt);
        ll mid = (tree[rt].l + tree[rt].r) >> 1;
        if (l <= mid) updata_plus(l, r, rt << 1, val);
        if (r > mid) updata_plus(l, r, rt << 1 | 1, val);
      
        pushup(rt);
    }
    void updata_ji(ll l, ll r, ll rt, ll val) {
        if (l <= tree[rt].l && r >= tree[rt].r) {
            tree[rt].sum = (tree[rt].sum*val)%p;
            tree[rt].minn *= val;
            tree[rt].maxn *= val;
            tree[rt].add = (tree[rt].add * val)%p;//延时标记
            tree[rt].mul = (tree[rt].mul * val)%p;
            return;
        }
        pushdown(rt);
        ll mid = (tree[rt].l + tree[rt].r) >> 1;
        if (l <= mid) updata_ji(l, r, rt << 1, val);
        if (r > mid) updata_ji(l, r, rt << 1 | 1, val);
        pushup(rt);
    }
    ll querySum(ll l, ll r, ll rt) {
        if (l <= tree[rt].l && r >= tree[rt].r) {
            return tree[rt].sum;
        }
        pushdown(rt);
        ll mid = (tree[rt].l + tree[rt].r) >> 1;
        ll ans = 0;
        ll Max = 0;
        ll Min = inf;
        if (l <= mid) {
            ans = querySum(l, r, rt << 1);
        }
        if (r > mid) {
            ans += querySum(l, r, rt << 1 | 1);
        }
        return ans%p;
    }
    ll queryJi(ll l, ll r, ll rt)
    {
        if (l <= tree[rt].l && r >= tree[rt].r) {
            return tree[rt].ji;
        }
        pushdown(rt);
        ll mid = (tree[rt].l + tree[rt].r) >> 1;
        ll ans = 1;
        ll Max = 0;
        ll Min = inf;
        if (l <= mid) {
            ans = queryJi(l, r, rt << 1);
        }
        if (r > mid) {
            ans *= queryJi(l, r, rt << 1 | 1);
        }
        return ans;
    }
    ll queryMin(ll l, ll r, ll rt) {
        if (l <= tree[rt].l && r >= tree[rt].r) {
            return tree[rt].minn;
        }
        pushdown(rt);
        ll mid = (tree[rt].l + tree[rt].r) >> 1;
        ll ans = 0;
        ll Max = 0;
        ll Min = inf;
        if (l <= mid) {
            Min = min(queryMin(l, r, rt << 1), Min);
        }
        if (r > mid) {
            Min = min(queryMin(l, r, rt << 1 | 1), Min);
        }
        return Min;
    }
    ll queryMax(ll l, ll r, ll rt) {
        if (l <= tree[rt].l && r >= tree[rt].r) {
            return tree[rt].maxn;
        }
        pushdown(rt);
        ll mid = (tree[rt].l + tree[rt].r) >> 1;
        ll ans = 0;
        ll Max = 0;
        ll Min = inf;
        if (l <= mid) {
            Max = max(queryMax(l, r, rt << 1), Max);
        }
        if (r > mid) {
            Max = max(queryMax(l, r, rt << 1 | 1), Max);
        }
     
        return Max;
    }
    int main()
    {
        ll i, j, k;
        ll n, m;
        ll x, y;
        cin >> n >> m >> p;
        build(1, n, 1);
        while (m--)
        {
            ll g;
            cin >> g;
            if (g == 1)
            {
                cin >> x >> y >> k;
                updata_ji(x, y, 1,k);
            }
            if(g==2)
            {
                cin >> x >> y >> k;
                updata_plus(x, y, 1, k);
            }
            if (g == 3)
            {
                cin >> x >> y;
                cout << querySum(x, y, 1) % p << endl;
            }
    
        }
    }
  • 相关阅读:
    ASCII码表以及不同进制间的O(1)转换
    四则运算表达式的语法分析
    语法分析器初步学习——LISP语法分析
    ASC与HEX之间的转换
    字节存储数据
    进制之间的转换
    java多线程CountDownLatch
    java反射机制
    java注解
    使用javafx实现视频播放器
  • 原文地址:https://www.cnblogs.com/ch-hui/p/12623871.html
Copyright © 2011-2022 走看看