星际旅行

算法: 线段树 、离散化

题意:

你需要维护\(3\)维空间的\(n( 1 \leq n \leq 10^9)\)个点,初始时这些点的三维坐标都是\(0\)。将有以下\(4\)种操作\(m(1 \leq m \leq 4 \times 10 ^4)\)次。

  1. 给区间\([left , right]\)的所有点的三维坐标分别加上\(a , b , c\)

  2. 给区间\([left , right]\)的所有点的三维坐标分别乘上\(k\)

  3. 将区间\([left , right]\)内的点的\(x,y,z\)坐标分别变换成\(y , z , x\)

  4. 询问区间\([left , right]\)内所有点的\(x\)坐标和的平方、\(y\)坐标和的平方、\(z\)坐标和的平方和

思路:

操作\(1,2\)是线段树模板\(2\)的基本操作,正常维护即可

操作\(3\)增加一个\(tag\)用于标记是否需要进行变换,需要模\(3\)

操作\(4\)就是正常的区间查询

考虑到本题\(n\)的范围很大,所以将所有询问读入后对\(left , right + 1\)的合并集合进行排序离散化,维护的是开区间,对于单点的操作,实际表示的是左闭右开的区间,长度就是相应的\(right – left\)

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(8 * m)\)

参考代码

#include<bits/stdc++.h>
#include<unordered_map>
#define for_int(i,a,b) for(int i=(a);i<=(b);++i)
#define rep_int(i,a,b) for(int i=(a);i>=(b);--i)
#define for_ll(i,a,b) for(ll i=(a);i<=(b);++i)
#define rep_ll(i,a,b) for(ll i=(a);i>=(b);--i)
#define Ios std::ios::sync_with_stdio(false),std::cin.tie(0)
#define ull unsigned long long
#define ll long long
#define db double
#define PII std::pair<int,int>
#define PLI std::pair<long long , int>
template<class T> void chkmax(T& a, T b) { a > b ? (a = a) : (a = b); }
template<class T> void chkmin(T& a, T b) { a > b ? (a = b) : (a = a); }
template<class T> T min(T a, T b) { return a > b ? b : a; }
template<class T> T max(T a, T b) { return a < b ? b : a; }
template<class T> T abs(T a) { return a < 0 ? -a : a; }
//using namespace std;
/*
    1.注意边界情况
    2.优先考虑时间复杂度
!!! 3.求最大值时,答案应至多初始化为INT_MIN;求最小值时,答案应至少初始化为INT_MAX
    4.遇事不决先暴力
    5.代码要写简洁
    6.计数题要开long long
*/
//快速IO
template<class T>
inline bool rd(T& ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return true;
}
template<class T>
inline void print(T x) {
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
    return;
}
using std::vector;
using std::queue;
using std::string;
using std::map;
using std::unordered_map;
using std::priority_queue;
using std::cout;
using std::cin;


const int mod = 1e9 + 7;
const int N = 1e6 + 5;

struct Segment {
    int lr, rs, mid;
    long long x, y, z, tagx, tagy, tagz, tag2, tag3;
};
Segment tree[N << 2];
struct Points {
    long long x, y, z;
    Points(long long _x = 0, long long _y = 0, long long _z = 0) {
        x = _x; y = _y; z = _z;
    }
    Points operator += (const Points& a) {
        x = (x + a.x) % mod;
        y = (y + a.y) % mod;
        z = (z + a.z) % mod;
        return *this;
    }
};
int a[N], tot;
void pushUp(int rt) {
    tree[rt].x = (tree[rt << 1].x + tree[rt << 1 | 1].x) % mod;
    tree[rt].y = (tree[rt << 1].y + tree[rt << 1 | 1].y) % mod;
    tree[rt].z = (tree[rt << 1].z + tree[rt << 1 | 1].z) % mod;
}
void buildTree(int rt, int lr, int rs) {
    tree[rt].lr = lr; tree[rt].rs = rs;
    tree[rt].tag2 = 1;
    if (lr == rs) return;
    int mid = tree[rt].mid = lr + rs >> 1;
    buildTree(rt << 1, lr, mid);
    buildTree(rt << 1 | 1, mid + 1, rs);
    pushUp(rt);
    return;
}
void pushDown(int rt) {
    if (tree[rt].tag3 == 0);
    else if (tree[rt].tag3 == 1) {
        std::swap(tree[rt << 1].x, tree[rt << 1].y);
        std::swap(tree[rt << 1].y, tree[rt << 1].z);

        std::swap(tree[rt << 1].tagx, tree[rt << 1].tagy);
        std::swap(tree[rt << 1].tagy, tree[rt << 1].tagz);
        tree[rt << 1].tag3 = (tree[rt << 1].tag3 + 1) % 3;

        std::swap(tree[rt << 1 | 1].x, tree[rt << 1 | 1].y);
        std::swap(tree[rt << 1 | 1].y, tree[rt << 1 | 1].z);

        std::swap(tree[rt << 1 | 1].tagx, tree[rt << 1 | 1].tagy);
        std::swap(tree[rt << 1 | 1].tagy, tree[rt << 1 | 1].tagz);
        tree[rt << 1 | 1].tag3 = (tree[rt << 1 | 1].tag3 + 1) % 3;
        tree[rt].tag3 = 0;
    }
    else if (tree[rt].tag3 == 2) {
        std::swap(tree[rt << 1].x, tree[rt << 1].z);
        std::swap(tree[rt << 1].z, tree[rt << 1].y);
        std::swap(tree[rt << 1].tagx, tree[rt << 1].tagz);
        std::swap(tree[rt << 1].tagz, tree[rt << 1].tagy);

        tree[rt << 1].tag3 = (tree[rt << 1].tag3 + 2) % 3;

        std::swap(tree[rt << 1 | 1].x, tree[rt << 1 | 1].z);
        std::swap(tree[rt << 1 | 1].z, tree[rt << 1 | 1].y);
        std::swap(tree[rt << 1 | 1].tagx, tree[rt << 1 | 1].tagz);
        std::swap(tree[rt << 1 | 1].tagz, tree[rt << 1 | 1].tagy);
        tree[rt << 1 | 1].tag3 = (tree[rt << 1 | 1].tag3 + 2) % 3;
        tree[rt].tag3 = 0;
    }
    if (tree[rt].tag2 != 1) {
        long long tag2 = tree[rt].tag2;
        tree[rt].tag2 = 1;
        tree[rt << 1].x = tree[rt << 1].x * tag2 % mod;
        tree[rt << 1].y = tree[rt << 1].y * tag2 % mod;
        tree[rt << 1].z = tree[rt << 1].z * tag2 % mod;
        tree[rt << 1].tagx = tree[rt << 1].tagx * tag2 % mod;
        tree[rt << 1].tagy = tree[rt << 1].tagy * tag2 % mod;
        tree[rt << 1].tagz = tree[rt << 1].tagz * tag2 % mod;
        tree[rt << 1].tag2 = tree[rt << 1].tag2 * tag2 % mod;

        tree[rt << 1 | 1].x = tree[rt << 1 | 1].x * tag2 % mod;
        tree[rt << 1 | 1].y = tree[rt << 1 | 1].y * tag2 % mod;
        tree[rt << 1 | 1].z = tree[rt << 1 | 1].z * tag2 % mod;
        tree[rt << 1 | 1].tagx = tree[rt << 1 | 1].tagx * tag2 % mod;
        tree[rt << 1 | 1].tagy = tree[rt << 1 | 1].tagy * tag2 % mod;
        tree[rt << 1 | 1].tagz = tree[rt << 1 | 1].tagz * tag2 % mod;
        tree[rt << 1 | 1].tag2 = tree[rt << 1 | 1].tag2 * tag2 % mod;
    }
    int lenl = a[tree[rt << 1].rs + 1] - a[tree[rt << 1].lr];
    int lenr = a[tree[rt << 1 | 1].rs + 1] - a[tree[rt << 1 | 1].lr];
    if (tree[rt].tagx != 0) {
        long long tag = tree[rt].tagx;
        tree[rt].tagx = 0;
        tree[rt << 1].x = (tree[rt << 1].x + tag * lenl) % mod;
        tree[rt << 1].tagx = (tree[rt << 1].tagx + tag) % mod;
        tree[rt << 1 | 1].x = (tree[rt << 1 | 1].x + tag * lenr) % mod;
        tree[rt << 1 | 1].tagx = (tree[rt << 1 | 1].tagx + tag) % mod;
    }
    if (tree[rt].tagy != 0) {
        long long tag = tree[rt].tagy;
        tree[rt].tagy = 0;
        tree[rt << 1].y = (tree[rt << 1].y + tag * lenl) % mod;
        tree[rt << 1].tagy = (tree[rt << 1].tagy + tag) % mod;
        tree[rt << 1 | 1].y = (tree[rt << 1 | 1].y + tag * lenr) % mod;
        tree[rt << 1 | 1].tagy = (tree[rt << 1 | 1].tagy + tag) % mod;
    }
    if (tree[rt].tagz != 0) {
        long long tag = tree[rt].tagz;
        tree[rt].tagz = 0;
        tree[rt << 1].z = (tree[rt << 1].z + tag * lenl) % mod;
        tree[rt << 1].tagz = (tree[rt << 1].tagz + tag) % mod;
        tree[rt << 1 | 1].z = (tree[rt << 1 | 1].z + tag * lenr) % mod;
        tree[rt << 1 | 1].tagz = (tree[rt << 1 | 1].tagz + tag) % mod;
    }
    
    return;
}
Points P;
void update(int rt, int lr, int rs) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        long long len = a[tree[rt].rs + 1] - a[tree[rt].lr];
        tree[rt].x = (tree[rt].x + P.x * len) % mod;
        tree[rt].y = (tree[rt].y + P.y * len) % mod;
        tree[rt].z = (tree[rt].z + P.z * len) % mod;
        tree[rt].tagx = (tree[rt].tagx + P.x) % mod;
        tree[rt].tagy = (tree[rt].tagy + P.y) % mod;
        tree[rt].tagz = (tree[rt].tagz + P.z) % mod;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) update(rt << 1, lr, rs);
    if (tree[rt].mid < rs) update(rt << 1 | 1, lr, rs);
    pushUp(rt);
    return;
}
void update(int rt, int lr, int rs , long long val) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        tree[rt].x = tree[rt].x * val % mod;
        tree[rt].y = tree[rt].y * val % mod;
        tree[rt].z = tree[rt].z * val % mod;
        tree[rt].tagx = tree[rt].tagx * val % mod;
        tree[rt].tagy = tree[rt].tagy * val % mod;
        tree[rt].tagz = tree[rt].tagz * val % mod;
        tree[rt].tag2 = tree[rt].tag2 * val % mod;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) update(rt << 1, lr, rs , val);
    if (tree[rt].mid < rs) update(rt << 1 | 1, lr, rs , val);
    pushUp(rt);
    return;
}
void changeUpdate(int rt, int lr, int rs) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        std::swap(tree[rt].x, tree[rt].y);
        std::swap(tree[rt].y, tree[rt].z);
        std::swap(tree[rt].tagx, tree[rt].tagy);
        std::swap(tree[rt].tagy, tree[rt].tagz);
        tree[rt].tag3 = (tree[rt].tag3 + 1) % 3;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) changeUpdate(rt << 1, lr, rs);
    if (tree[rt].mid < rs)  changeUpdate(rt << 1 | 1, lr, rs);
    pushUp(rt);
    return;
}
Points query(int rt, int lr, int rs) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return Points(0 , 0 , 0);
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) return Points(tree[rt].x, tree[rt].y, tree[rt].z);
    Points res;
    pushDown(rt);
    if (tree[rt].mid >= lr) res += query(rt << 1, lr, rs);
    if (tree[rt].mid < rs) res += query(rt << 1 | 1, lr, rs);
    return res;
}
struct Query {
    int op, lr, rs, a, b, c, k;
};
Query q[N];
int n, m, op, lr, rs, x, y, z, k;
int getid(int val) {
    return std::lower_bound(a + 1, a + 1 + tot, val) - a;
}
int main() {
    rd(n); rd(m);
    for (int i = 1; i <= m; ++i) {
        rd(op); rd(lr); rd(rs);
        a[++tot] = lr; a[++tot] = rs + 1;
        q[i].op = op; q[i].lr = lr; q[i].rs = rs + 1;
        if (op == 1) {
            rd(x); rd(y); rd(z);
            q[i].a = x; q[i].b = y; q[i].c = z;
        }
        else if (op == 2) {
            rd(k); q[i].k = k;
        }
    }
    std::sort(a + 1, a + 1 + tot);
    tot = std::unique(a + 1, a + 1 + tot) - a - 1;
    buildTree(1, 1, tot);
    for (int i = 1; i <= m; ++i) {
        op = q[i].op; lr = getid(q[i].lr); rs = getid(q[i].rs) - 1;
        if (op == 1) {
            P = { q[i].a , q[i].b , q[i].c };
            update(1, lr, rs);
        }
        else if (op == 2) update(1, lr, rs, q[i].k);
        else if(op == 3) changeUpdate(1, lr, rs);
        else {
            Points ans = query(1, lr, rs);
            long long res = ans.x * ans.x % mod;
            res += ans.y * ans.y % mod;
            res += ans.z * ans.z % mod;
            res %= mod;
            print(res); puts("");
        }

    }
    return 0;
}

原文地址:http://www.cnblogs.com/cherish-/p/16852043.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性