202012-5 星际旅行 (线段树模板60分)记录一下

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 1e5 + 5;
const ll MOD = 1e9 + 7;

struct Node {
    ll l, r;
    ll x = 0, y = 0, z = 0;
    ll mul = 1;
    ll addx = 0;
    ll addy = 0;
    ll addz = 0;
}tree[maxn << 2];
int n, m;

void buildTree(ll i, ll l, ll r) {
    tree[i].l = l;
    tree[i].r = r;
    if (l == r) {
        return;
    }

    ll mid = l + ((r - l) >> 1);
    ll lef = i << 1, rig = i << 1 | 1;
    buildTree(lef, l, mid);
    buildTree(rig, mid + 1, r);
    tree[i].x = (tree[lef].x + tree[rig].x) % MOD;
    tree[i].y = (tree[lef].y + tree[rig].y) % MOD;
    tree[i].z = (tree[lef].z + tree[rig].z) % MOD;
}

void pushDown(ll rt) {
    ll lef = rt << 1, rig = rt << 1 | 1;
    tree[lef].x = ((tree[rt].mul * tree[lef].x) % MOD + ((tree[lef].r - tree[lef].l + 1) * tree[rt].addx) % MOD) % MOD;
    tree[lef].y = ((tree[rt].mul * tree[lef].y) % MOD + ((tree[lef].r - tree[lef].l + 1) * tree[rt].addy) % MOD) % MOD;
    tree[lef].z = ((tree[rt].mul * tree[lef].z) % MOD + ((tree[lef].r - tree[lef].l + 1) * tree[rt].addz) % MOD) % MOD;

    tree[rig].x = ((tree[rt].mul * tree[rig].x) % MOD + ((tree[rig].r - tree[rig].l + 1) * tree[rt].addx) % MOD) % MOD;
    tree[rig].y = ((tree[rt].mul * tree[rig].y) % MOD + ((tree[rig].r - tree[rig].l + 1) * tree[rt].addy) % MOD) % MOD;
    tree[rig].z = ((tree[rt].mul * tree[rig].z) % MOD + ((tree[rig].r - tree[rig].l + 1) * tree[rt].addz) % MOD) % MOD;

    tree[lef].mul = (tree[rt].mul * tree[lef].mul) % MOD;
    tree[rig].mul = (tree[rt].mul * tree[rig].mul) % MOD;

    tree[lef].addx = ((tree[rt].mul * tree[lef].addx) % MOD + tree[rt].addx) % MOD;
    tree[lef].addy = ((tree[rt].mul * tree[lef].addy) % MOD + tree[rt].addy) % MOD;
    tree[lef].addz = ((tree[rt].mul * tree[lef].addz) % MOD + tree[rt].addz) % MOD;

    tree[rig].addx = ((tree[rt].mul * tree[rig].addx) % MOD + tree[rt].addx) % MOD;
    tree[rig].addy = ((tree[rt].mul * tree[rig].addy) % MOD + tree[rt].addy) % MOD;
    tree[rig].addz = ((tree[rt].mul * tree[rig].addz) % MOD + tree[rt].addz) % MOD;

    tree[rt].addx = 0; tree[rt].mul = 1;
    tree[rt].addy = 0; tree[rt].addz = 0;
}

void add(ll i, ll l, ll r, ll a, ll b, ll c) {
    if (tree[i].l >= l && tree[i].r <= r) {
        tree[i].x = (tree[i].x + a * (tree[i].r - tree[i].l + 1)) % MOD;
        tree[i].y = (tree[i].y + b * (tree[i].r - tree[i].l + 1)) % MOD;
        tree[i].z = (tree[i].z + c * (tree[i].r - tree[i].l + 1)) % MOD;

        tree[i].addx = (tree[i].addx + a) % MOD;
        tree[i].addy = (tree[i].addy + b) % MOD;
        tree[i].addz = (tree[i].addz + c) % MOD;
        return;
    }

    pushDown(i);
    ll lef = i << 1, rig = i << 1 | 1;
    if (tree[lef].r >= l) add(lef, l, r, a, b, c);
    if (tree[rig].l <= r) add(rig, l, r, a, b, c);
    tree[i].x = (tree[lef].x + tree[rig].x) % MOD;
    tree[i].y = (tree[lef].y + tree[rig].y) % MOD;
    tree[i].z = (tree[lef].z + tree[rig].z) % MOD;
}

void multi(ll i, ll l, ll r, ll k) {
    if (tree[i].l >= l && tree[i].r <= r) {
        tree[i].x = (tree[i].x * k) % MOD;
        tree[i].y = (tree[i].y * k) % MOD;
        tree[i].z = (tree[i].z * k) % MOD;

        tree[i].addx = (tree[i].addx * k) % MOD;
        tree[i].addy = (tree[i].addy * k) % MOD;
        tree[i].addz = (tree[i].addz * k) % MOD;
        tree[i].mul = (tree[i].mul * k) % MOD;
        return;
    }

    pushDown(i);
    ll lef = i << 1, rig = i << 1 | 1;
    if (tree[lef].r >= l) multi(lef, l, r, k);
    if (tree[rig].l <= r) multi(rig, l, r, k);
    tree[i].x = (tree[lef].x + tree[rig].x) % MOD;
    tree[i].y = (tree[lef].y + tree[rig].y) % MOD;
    tree[i].z = (tree[lef].z + tree[rig].z) % MOD;
}

ll* search(ll i, ll l, ll r) {
	ll* ans = new ll[3];	// 重点 
	ans[0] = 0; ans[1] = 0; ans[2] = 0;
    if (tree[i].l > r || tree[i].r < l) return ans;
    if (tree[i].l >= l && tree[i].r <= r) {
    	ans[0] = tree[i].x;
		ans[1] = tree[i].y;
		ans[2] = tree[i].z;
		return ans;
	}

    pushDown(i);
    if (tree[i << 1].r >= l) {
        ll* t = search(i << 1, l, r);
        ans[0] = (ans[0] + t[0]) % MOD;
        ans[1] = (ans[1] + t[1]) % MOD;
        ans[2] = (ans[2] + t[2]) % MOD;
    }

    if (tree[i << 1 | 1].l <= r) {
        ll* t = search(i << 1 | 1, l, r);
        ans[0] = (ans[0] + t[0]) % MOD;
        ans[1] = (ans[1] + t[1]) % MOD;
        ans[2] = (ans[2] + t[2]) % MOD;
    }

    return ans;
}

ll calc(ll t[]) {
    return (((t[0] % MOD) * (t[0] % MOD)) % MOD + ((t[1] % MOD) * (t[1] % MOD)) % MOD
        + ((t[2] % MOD) * (t[2] % MOD)) % MOD) % MOD;
}

int main() {
    scanf("%d %d", &n, &m);
    if (n <= 1000 && m <= 1000) {
        ll x[1005] = {0}, y[1005] = {0}, z[1005] = {0};
        int op, l, r; ll k;
        while (m--) {
            scanf("%d%d%d", &op, &l, &r);
            if (op == 1) {
                ll a, b, c;
                scanf("%lld%lld%lld", &a, &b, &c);
                for (int i = l; i <= r; i++) {
                    x[i] = (x[i] + a) % MOD, y[i] = (y[i] + b) % MOD, z[i] = (z[i] + c) % MOD;
                }
            } else if (op == 2) {
                scanf("%lld", &k);
                for (int i = l; i <= r; i++) {
                    x[i] = (x[i] * k) % MOD, y[i] = (y[i] * k) % MOD, z[i] = (z[i] * k) % MOD;
                }
            } else if (op == 3) {
                for (int i = l; i <= r; i++) {
                    swap(x[i], y[i]);
                    swap(y[i], z[i]);
                }
            } else {
                ll X = 0, Y = 0, Z = 0;
                for (int i = l; i <= r; i++) {
                    X = (X + x[i]) % MOD, Y = (Y + y[i]) % MOD, Z = (Z + z[i]) % MOD;
                }
                printf("%lld\n", (X * X % MOD + Y * Y % MOD + Z * Z % MOD) % MOD);
            }
        }
    } else {
    	buildTree(1, 1, n);
	    while (m --) {
	        int op; scanf("%d", &op);
	        if (op == 1) {
	            int l, r, a, b, c;
	            scanf("%d %d %d %d %d", &l, &r, &a, &b, &c);
	            add(1, l, r, a, b, c);
	        } else if (op == 2) {
	            int l, r, k;
	            scanf("%d %d %d", &l, &r, &k);
	            multi(1, l, r, k);
	        } else if (op == 3) {
	            int a, b; scanf("%d %d", &a, &b);
	        } else if (op == 4) {
	            int l, r; scanf("%d %d", &l, &r);
	            ll* t = search(1, l, r);
	            printf("%lld\n", calc(t));
	        }
	    }
	}
    
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值