#include #define For(i, a, b) for (int(i) = (int)(a); (i) < (int)(b); ++(i)) #define rFor(i, a, b) for (int(i) = (int)(a)-1; (i) >= (int)(b); --(i)) #define rep(i, n) For((i), 0, (n)) #define rrep(i, n) rFor((i), (n), 0) #define fi first #define se second using namespace std; typedef long long lint; typedef unsigned long long ulint; typedef pair pii; typedef pair pll; template bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; } template bool chmin(T &a, const T &b) { if (a > b) { a = b; return true; } return false; } template T div_floor(T a, T b) { if (b < 0) a *= -1, b *= -1; return a >= 0 ? a / b : (a + 1) / b - 1; } template T div_ceil(T a, T b) { if (b < 0) a *= -1, b *= -1; return a > 0 ? (a - 1) / b + 1 : a / b; } constexpr lint mod = 1000000007; constexpr lint INF = mod * mod; constexpr int MAX = 200010; template struct LazySegTree { using F = function; using G = function; using H = function; using P = function; int sz = 1, seq_sz; F f; G g; H h; T et; E ee; P p; int cur = 0; vector node; vector lazy; vector idx, len; LazySegTree( int sz_, T et_, E ee_, F f_, G g_, H h_, P p_ = [](E a, int b) { return a; }) : seq_sz(sz_), et(et_), ee(ee_), f(f_), g(g_), h(h_), p(p_) { while (sz < sz_) sz <<= 1; node.resize(sz << 1, et); lazy.resize(sz << 1, ee); idx.resize(sz, -1); len.resize(sz << 1, 0); For(i, sz, sz << 1) len[i] = 1; rFor(i, sz, 1) len[i] = len[i << 1] + len[(i << 1) + 1]; } void build(vector &a) { rep(i, a.size()) node[i + sz] = a[i]; rFor(i, sz, 1) node[i] = f(node[i << 1], node[(i << 1) + 1]); } void build(T x) { rep(i, seq_sz) node[i + sz] = x; rFor(i, sz, 1) node[i] = f(node[i << 1], node[(i << 1) + 1]); } inline void push(int i) { if (lazy[i] == ee) return; if (i < sz) { lazy[i << 1] = h(lazy[i << 1], lazy[i]); node[i << 1] = g(node[i << 1], p(lazy[i], len[i << 1])); lazy[(i << 1) + 1] = h(lazy[(i << 1) + 1], lazy[i]); node[(i << 1) + 1] = g(node[(i << 1) + 1], p(lazy[i], len[(i << 1) + 1])); } lazy[i] = ee; } inline void prop(int l, int r) { cur = 0; if (l == sz && r == sz << 1) return; l = (l / (l & -l)) >> 1; r = (r / (r & -r)) >> 1; while (l > 1 || r > 1) { if (l >= r) { idx[cur++] = l; l >>= 1; } else { idx[cur++] = r; r >>= 1; } } idx[cur++] = 1; rrep(k, cur) push(idx[k]); } void update(int l, int r, E x) { l += sz; r += sz; prop(l, r); for (; l < r; l >>= 1, r >>= 1) { if (l & 1) { lazy[l] = h(lazy[l], x); node[l] = g(node[l], p(x, len[l])); ++l; } if (r & 1) { --r; lazy[r] = h(lazy[r], x); node[r] = g(node[r], p(x, len[r])); } } rep(k, cur) { int i = idx[k]; if (i < sz) node[i] = f(node[i << 1], node[(i << 1) + 1]); } } T query(int l, int r) { l += sz; r += sz; prop(l, r); T vl = et, vr = et; for (; l < r; l >>= 1, r >>= 1) { if (l & 1) vl = f(vl, node[l++]); if (r & 1) vr = f(node[--r], vr); } return f(vl, vr); } }; using mat = array, 3>; mat mul(mat a, mat b) { mat c; rep(i, 3) rep(j, 3) { c[i][j] = 0; rep(k, 3) c[i][j] += a[i][k] * b[k][j]; } return c; } array mul(mat a, array v) { array vv = {0, 0, 0}; rep(i, 3) rep(j, 3) vv[i] += a[i][j] * v[j]; return vv; } int main() { int n, q; scanf("%d%d", &n, &q); array v[n + 1]; int len[n]; rep(i, n) len[i] = 1; rep(i, n + 1) v[i] = {i, 0, 1}; auto f = [&](mat a, mat b) { return mul(a, b); }; mat e; rep(i, 3) { rep(j, 3) e[i][j] = 0; e[i][i] = 1; } LazySegTree lst(n + 1, e, e, f, f, f); rep(_, q) { int t; scanf("%d", &t); if (t == 0) { int pos, x; scanf("%d%d", &pos, &x); --pos; auto p = mul(lst.query(pos, pos + 1), v[pos]); auto q = mul(lst.query(pos + 1, pos + 2), v[pos + 1]); mat a; rep(i, 3) rep(j, 3) a[i][j] = 0; a[0][0] = a[1][1] = cos(x * M_PI / 180 - atan2(q[1] - p[1], q[0] - p[0])); a[0][1] = a[1][0] = sin(x * M_PI / 180 - atan2(q[1] - p[1], q[0] - p[0])); a[0][1] *= -1; a[2][2] = 1; /*rep(i, 3) { rep(j, 3) printf("%lf ", a[i][j]); printf("\n"); }*/ mat b; rep(i, 3) { rep(j, 3) b[i][j] = 0; b[i][i] = 1; } b[0][2] = -p[0]; b[1][2] = -p[1]; /*rep(i, 3) { rep(j, 3) printf("%lf ", b[i][j]); printf("\n"); }*/ lst.update(pos + 1, n + 1, b); lst.update(pos + 1, n + 1, a); b[0][2] *= -1; b[1][2] *= -1; lst.update(pos + 1, n + 1, b); } else if (t == 1) { int pos, x; scanf("%d%d", &pos, &x); --pos; auto p = mul(lst.query(pos, pos + 1), v[pos]); auto q = mul(lst.query(pos + 1, pos + 2), v[pos + 1]); mat b; rep(i, 3) { rep(j, 3) b[i][j] = 0; b[i][i] = 1; } b[0][2] = (q[0] - p[0]) * (x - len[pos]) / len[pos]; b[1][2] = (q[1] - p[1]) * (x - len[pos]) / len[pos]; len[pos] = x; lst.update(pos + 1, n + 1, b); } else { int i; scanf("%d", &i); auto a = lst.query(i, i + 1); auto p = mul(a, v[i]); printf("%.10lf %.10lf\n", p[0], p[1]); } printf("%d\n", _); rep(i, n + 1) { auto p = mul(lst.query(i, i + 1), v[i]); printf("(%lf %lf %lf)\n", p[0], p[1], p[2]); } } }