绕原点逆时针旋转,可以通过矩阵变换描述
如果绕特定的点 旋转角度
,可以写成
先平移 ,再绕原点旋转,最后再平移
,构造仿射变换如下
另外注意矩阵变换是满足分配律的,比如对于当前星星 ,对于变换
所以只需要用线段树维护 ,分别表示区间中所有星星
坐标的和
构造仿射变换
初始化,对于每一个星星
,
,建立线段树
对于操作
,即执行仿射变换
,只需要
,难点在于
和
怎么写,以及懒标记处理
每次修改,难点在于
如何处理
初始化为单位矩阵
,每一次对线段树节点
执行变换
时
执行矩阵乘法,并且下传延迟标记
递归到的每一个子区间都被修改了,后面的修改是基于前面修改基础上的
对于子区间,执行,右子树同理
操作只需要执行,
对于操作
的问询,只需要注意每次递归查询时候,下传延迟标记,最后找到表示区间
的节点
就是答案,注意在修改操作中更新
需要取
坑点提示
所以维护的矩阵变换应该是
其中 表示线段树
节点的区间长度
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <bitset>
#include <assert.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
#define Cmp(a, b) memcmp(a, b, sizeof(b))
#define Cpy(a, b) memcpy(a, b, sizeof(b))
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define _forS(i, l, r) for(set<int>::iterator i = (l); i != (r); i++)
#define _rep(i, l, r) for(int i = (l); i <= (r); i++)
#define _for(i, l, r) for(int i = (l); i < (r); i++)
#define _forDown(i, l, r) for(int i = (l); i >= r; i--)
#define debug_(ch, i) printf(#ch"[%d]: %d\n", i, ch[i])
#define debug_m(mp, p) printf(#mp"[%d]: %d\n", p->first, p->second)
#define debugS(str) cout << "dbg: " << str << endl;
#define debugArr(arr, x, y) _for(i, 0, x) { _for(j, 0, y) printf("%c", arr[i][j]); printf("\n"); }
#define _forPlus(i, l, d, r) for(int i = (l); i + d < (r); i++)
#define lowbit(i) (i & (-i))
#define MPR(a, b) make_pair(a, b)
pair<int, int> crack(int n) {
int st = sqrt(n);
int fac = n / st;
while (n % st) {
st += 1;
fac = n / st;
}
return make_pair(st, fac);
}
inline ll qpow(ll a, int n) {
ll ans = 1;
for(; n; n >>= 1) {
if(n & 1) ans *= 1ll * a;
a *= a;
}
return ans;
}
template <class t>
inline bool chmax(T& a, T b) {
if(a < b) {
a = b;
return true;
}
return false;
}
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll ksc(ll a, ll b, ll mod) {
ll ans = 0;
for(; b; b >>= 1) {
if (b & 1) ans = (ans + a) % mod;
a = (a * 2) % mod;
}
return ans;
}
ll ksm(ll a, ll b, ll mod) {
ll ans = 1 % mod;
a %= mod;
for(; b; b >>= 1) {
if (b & 1) ans = ksc(ans, a, mod);
a = ksc(a, a, mod);
}
return ans;
}
template <class t>
inline bool chmin(T& a, T b) {
if(a > b) {
a = b;
return true;
}
return false;
}
template<class t>
bool lexSmaller(vector<t> a, vector<t> b) {
int n = a.size(), m = b.size();
int i;
for(i = 0; i < n && i < m; i++) {
if (a[i] < b[i]) return true;
else if (b[i] < a[i]) return false;
}
return (i == n && i < m);
}
// ============================================================== //
const int maxn = 1e5 + 500;
const int mod = 998244353;
int n, m;
typedef vector<vector<ll> > Matrix;
Matrix I(3, vector<ll>(3, 0));
void init() {
for (int i = 0; i < 3; i++) I[i][i] = 1;
}
struct Point {
int x, y;
} a[maxn];
Matrix trans(const Matrix &A, const Matrix &B) {
int _n = A.size(), _m = B[0].size();
Matrix res(_n, vector<ll> (_m, 0));
for (int i = 0; i < _n; i++) {
for (int j = 0; j < _m; j++)
for (int k = 0; k < (int)A[0].size(); k++)
res[i][j] = res[i][j] + A[i][k] * B[k][j];
}
return res;
}
Matrix mul(const Matrix &A, const Matrix &B) {
int _n = A.size(), _m = B[0].size();
Matrix res(_n, vector<ll> (_m, 0));
for (int i = 0; i < _n; i++) {
for (int j = 0; j < _m; j++)
for (int k = 0; k < (int)A[0].size(); k++)
res[i][j] = (res[i][j] + A[i][k] * B[k][j] + mod) % mod;
}
return res;
}
Matrix get_matrix(int X, int Y) {
Matrix A(3, vector<ll>(3, 0));
for (int i = 0; i < 3; i++) A[i][i] = 1;
A[0][2] = X, A[1][2] = Y;
Matrix B(3, vector<ll>(3, 0));
B[0][1] = -1, B[1][0] = 1, B[2][2] = 1;
Matrix C(3, vector<ll>(3, 0));
for (int i = 0; i < 3; i++) C[i][i] = 1;
C[0][2] = -X, C[1][2] = -Y;
Matrix res = A;
res = trans(res, B);
res = trans(res, C);
return res;
}
namespace segTree {
struct node {
int l, r, tag;
ll sx, sy;
Matrix lazy;
} t[maxn << 2];
void pull(int p) {
t[p].sx = (t[p<<1].sx + t[p<<1|1].sx + mod) % mod;
t[p].sy = (t[p<<1].sy + t[p<<1|1].sy + mod) % mod;
}
void apply(int p, const Matrix& C) {
Matrix cur(3, vector<ll>(1, 0));
cur[0][0] = t[p].sx, cur[1][0] = t[p].sy, cur[2][0] = t[p].r-t[p].l+1;
Matrix nxt = trans(C, cur);
t[p].sx = nxt[0][0], t[p].sy = nxt[1][0];
}
void push(int p) {
if (!t[p].tag) return;
if (t[p].l == t[p].r) return;
t[p].tag = 0;
t[p<<1].tag = t[p<<1|1].tag = 1;
Matrix C = t[p].lazy;
t[p<<1].lazy = trans(C, t[p<<1].lazy);
t[p<<1|1].lazy = trans(C, t[p<<1|1].lazy);
t[p].lazy = I;
apply(p<<1, C), apply(p<<1|1, C);
}
void build(int p, int l, int r) {
t[p].l = l, t[p].r = r;
t[p].lazy = I;
if (l >= r) {
t[p].sx = a[l].x, t[p].sy = a[l].y;
return;
}
int mid = (l+r) >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pull(p);
}
void change(int p, const int l, const int r, const Matrix &P) {
if (l <= t[p].l && t[p].r <= r) {
t[p].tag = 1;
apply(p, P);
t[p].lazy = trans(P, t[p].lazy);
return;
}
push(p);
t[p].sx = t[p].sy = 0;
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) change(p<<1, l, r, P);
if (r > mid) change(p<<1|1, l, r, P);
pull(p);
}
ll query(int p, const int l, const int r, bool fl) {
if (l <= t[p].l && t[p].r <= r) {
if (fl == 0) return (t[p].sx + mod) % mod;
else return (t[p].sy + mod) % mod;
}
if (fl == 0) push(p);
ll ans = 0;
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) ans = (ans + query(p<<1, l, r, fl) + mod) % mod;
if (r > mid) ans = (ans + query(p<<1|1, l, r, fl) + mod) % mod;
return ans;
}
}
int main() {
//freopen("input.txt", "r", stdin);
cin >> n >> m;
init();
using namespace segTree;
// get data
for (int i = 1; i <= n; i++) scanf("%d%d", &a[i].x, &a[i].y);
build(1, 1, n);
// get change
while (m--) {
int op, li, ri;
scanf("%d%d%d", &op, &li, &ri);
//debug(op), debug(li), debug(ri);
if (op == 1) {
int X, Y;
scanf("%d%d", &X, &Y);
Matrix P = get_matrix(X, Y);
//dbg(P);
change(1, li, ri, P);
}
if (op == 2) {
ll sumx = query(1, li, ri, 0);
ll sumy = query(1, li, ri, 1);
//debug(sumy);
sumx = (sumx + mod) % mod, sumy = (sumy + mod) % mod;
ll ans = (sumx * sumy + mod) % mod;
printf("%lld\n", ans);
}
}
} 
京公网安备 11010502036488号