线段树区间乘积算法

 

这是算区间乘积的算法

#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;
        }

    }
}

 

posted @ 2020-03-22 21:27  ch_hui  阅读(520)  评论(0编辑  收藏  举报