星际旅行
算法: 线段树 、离散化
题意:
你需要维护\(3\)维空间的\(n( 1 \leq n \leq 10^9)\)个点,初始时这些点的三维坐标都是\(0\)。将有以下\(4\)种操作\(m(1 \leq m \leq 4 \times 10 ^4)\)次。
-
给区间\([left , right]\)的所有点的三维坐标分别加上\(a , b , c\)
-
给区间\([left , right]\)的所有点的三维坐标分别乘上\(k\)
-
将区间\([left , right]\)内的点的\(x,y,z\)坐标分别变换成\(y , z , x\)
-
询问区间\([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;
}
标签:rt,std,12,return,rs,CSP2020,T5,tree,lr
From: https://www.cnblogs.com/cherish-/p/16852043.html