#pragma GCC optimize ("Ofast") #include using namespace std; #define PI 3.14159265358979323846 void*wmem; char memarr[96000000]; template inline void walloc1d(T **arr, int x, void **mem = &wmem){ static int skip[16] = {0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; (*mem) = (void*)( ((char*)(*mem)) + skip[((unsigned long long)(*mem)) & 15] ); (*arr)=(T*)(*mem); (*mem)=((*arr)+x); } inline int my_getchar_unlocked(){ static char buf[1048576]; static int s = 1048576; static int e = 1048576; if(s == e && e == 1048576){ e = fread_unlocked(buf, 1, 1048576, stdin); s = 0; } if(s == e){ return EOF; } return buf[s++]; } inline void rd(int &x){ int k; int m=0; x=0; for(;;){ k = my_getchar_unlocked(); if(k=='-'){ m=1; break; } if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } if(m){ x=-x; } } inline int rd_int(void){ int x; rd(x); return x; } struct MY_WRITER{ char buf[1048576]; int s; int e; MY_WRITER(){ s = 0; e = 1048576; } ~MY_WRITER(){ if(s){ fwrite_unlocked(buf, 1, s, stdout); } } } ; MY_WRITER MY_WRITER_VAR; void my_putchar_unlocked(int a){ if(MY_WRITER_VAR.s == MY_WRITER_VAR.e){ fwrite_unlocked(MY_WRITER_VAR.buf, 1, MY_WRITER_VAR.s, stdout); MY_WRITER_VAR.s = 0; } MY_WRITER_VAR.buf[MY_WRITER_VAR.s++] = a; } inline void wt_L(char a){ my_putchar_unlocked(a); } int WRITER_DOUBLE_DIGIT = 15; inline int writerDigit_double(){ return WRITER_DOUBLE_DIGIT; } inline void writerDigit_double(int d){ WRITER_DOUBLE_DIGIT = d; } inline void wt_L(double x){ const int d = WRITER_DOUBLE_DIGIT; int k; int r; double v; if(x!=x || (x==x+1 && x==2*x)){ my_putchar_unlocked('E'); my_putchar_unlocked('r'); my_putchar_unlocked('r'); return; } if(x < 0){ my_putchar_unlocked('-'); x = -x; } x += 0.5 * pow(0.1, d); r = 0; v = 1; while(x >= 10*v){ v *= 10; r++; } while(r >= 0){ r--; k = floor(x / v); if(k >= 10){ k = 9; } if(k <= -1){ k = 0; } x -= k * v; v *= 0.1; my_putchar_unlocked(k + '0'); } if(d > 0){ my_putchar_unlocked('.'); v = 1; for(r=(0);r<(d);r++){ v *= 0.1; k = floor(x / v); if(k >= 10){ k = 9; } if(k <= -1){ k = 0; } x -= k * v; my_putchar_unlocked(k + '0'); } } } template inline T pow2_L(T a){ return a*a; } template struct segtree_pg{ int N; int logN; T*val; void malloc(int maxN, int once = 0); void walloc(int maxN, int once = 0, void **mem = &wmem); void free(void); T& operator[](int i); void setN(int n, int zerofill = 1, int dobuild = 1); void build(void); inline void build(int a); inline void change(int a, T v); inline T get(int a, int b); } ; struct hoge{ double x; double y; double th; } ; hoge gethoge(double th, double len){ hoge res; res.x = len * cos(th); res.y = len * sin(th); res.th = th; return res; } void segtree_pg_func(hoge &res, hoge a, hoge b){ double len; double arg; len = sqrt((pow2_L(b.x))+(pow2_L(b.y))); arg = atan2(b.y, b.x); res.x = a.x + len * cos(a.th + arg); res.y = a.y + len * sin(a.th + arg); res.th = a.th + b.th; } hoge arr[100000]; segtree_pg t; int main(){ int cTE1_r3A, i; wmem = memarr; int N; rd(N); hoge tmp; arr[0] = gethoge(0, 1); for(i=(1);i<(N);i++){ arr[i] = arr[i-1]; } t.walloc(N); t.setN(N); for(i=(0);i<(N);i++){ t[i] = arr[i]; } t.build(); int RZTsC2BF = rd_int(); for(cTE1_r3A=(0);cTE1_r3A<(RZTsC2BF);cTE1_r3A++){ int TYPE; rd(TYPE); int I; int X; if(TYPE==0){ rd(I);I += (-1); rd(X); arr[I].th = X * PI / 180; arr[I] = gethoge(X * PI / 180, sqrt((pow2_L(arr[I].x))+(pow2_L(arr[I].y)))); t.change(I, arr[I]); } if(TYPE==1){ rd(I);I += (-1); rd(X); arr[I] = gethoge(arr[I].th, X); t.change(I, arr[I]); } if(TYPE==2){ rd(I); tmp = t.get(0, I); wt_L(tmp.x); wt_L(' '); wt_L(tmp.y); wt_L('\n'); } } return 0; } template void segtree_pg::malloc(int maxN, int once /*= 0*/){ int i; for(i=1;i void segtree_pg::walloc(int maxN, int once /*= 0*/, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_pg::free(void){ delete [] val; } template T& segtree_pg::operator[](int i){ return val[N+i]; } template void segtree_pg::setN(int n, int zerofill /*= 1*/, int dobuild /*= 1*/){ int i; for(i=1,logN=0;i void segtree_pg::build(void){ for(int i=N-1;i;i--){ segtree_pg_func(val[i], val[2*i], val[2*i+1]); } } template inline void segtree_pg::build(int a){ while(a > 1){ a /= 2; segtree_pg_func(val[a], val[2*a], val[2*a+1]); } } template inline void segtree_pg::change(int a, T v){ val[a+N] = v; build(a+N); } template inline T segtree_pg::get(int a, int b){ T res; T tmp; int fga = 0; int fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ segtree_pg_func(res, res, val[a]); } else{ res = val[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ segtree_pg_func(tmp, val[b], tmp); } else{ tmp = val[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0){ return res; } if(fga==0 && fgb==1){ return tmp; } if(fga==1 && fgb==1){ segtree_pg_func(res, res, tmp); return res; } return res; } // cLay varsion 20200911-1 // --- original code --- // struct hoge{ // double x, y, th; // }; // // hoge gethoge(double th, double len){ // hoge res; // res.x = len * cos(th); // res.y = len * sin(th); // res.th = th; // return res; // } // // void segtree_pg_func(hoge &res, hoge a, hoge b){ // double len, arg; // len = sqrt(b.x ** 2 + b.y ** 2); // arg = atan2(b.y, b.x); // res.x = a.x + len * cos(a.th + arg); // res.y = a.y + len * sin(a.th + arg); // res.th = a.th + b.th; // } // // hoge arr[1d5]; // segtree_pg t; // // { // int @N; // hoge tmp; // // arr[0] = gethoge(0, 1); // rep(i,1,N) arr[i] = arr[i-1]; // // t.walloc(N); // t.setN(N); // rep(i,N) t[i] = arr[i]; // t.build(); // // REP(rd_int()){ // int @TYPE, I, X; // if(TYPE==0){ // rd(I--, X); // arr[I].th = X * PI / 180; // arr[I] = gethoge(X * PI / 180, sqrt(arr[I].x**2 + arr[I].y**2)); // t.change(I, arr[I]); // } // if(TYPE==1){ // rd(I--, X); // arr[I] = gethoge(arr[I].th, X); // t.change(I, arr[I]); // } // if(TYPE==2){ // rd(I); // tmp = t.get(0, I); // wt(tmp.x, tmp.y); // } // } // }