题意:有n根长度不尽相同的棍子,初始时它们首尾垂直相连,标号为1--n,第一根棍子的下端坐标为(0,0),上端坐标为(0,len[1]),其余棍子依次类推。接下来执行C此旋转,每次输入一个编号num和角度rad,使得第num根棍子和第num+1跟棍子间的逆时针角度变为rad度,求每次旋转后第n跟棍子端点的坐标。
思路:主要是是对此题如何转化为线段树的问题,这是通过对每个结点所在区间进行处理。
#include <cstdio> #include <cstring> #include <iostream> #include <stack> #include <queue> #include <map> #include <algorithm> #include <vector> #include <cmath> #define pi 3.141592653 using namespace std; const int maxn = 40005; typedef long long LL; int N,C; int L[maxn]; int S[maxn],A[maxn]; double vx[maxn],vy[maxn]; double ang[maxn]; double pre[maxn]; void init(int l,int r,int rt) { ang[rt] = vx[rt] = 0.0; if(r - l == 1) { vy[rt] = L[l]; } else{ int lch = rt*2+1; int rch = rt*2+2; int mid = (r + l )/2; init(l,mid,lch); init(mid,r,rch); vy[rt] = vy[lch] + vy[rch]; } } void change(int s,double a,int rt,int l,int r) { if(s <= l) return ; else if(s < r){ int lch = rt*2+1; int rch = rt*2+2; int mid = (l + r)/2; change(s,a,lch,l,mid); change(s,a,rch,mid,r); if(s <= mid) ang[rt] += a; double t = sin(ang[rt]); double c = cos(ang[rt]); vx[rt] = vx[lch] + (c*vx[rch] - t*vy[rch]); vy[rt] = vy[lch] + (t*vx[rch] + c*vy[rch]); } } void solve() { init(0,N,0); for(int i=1;i<N;i++) pre[i] = pi; for(int i=0;i<C;i++){ int s = S[i]; double a = A[i]/360.0*2*pi; change(s,a-pre[s],0,0,N); pre[s] = a; printf("%.2f %.2f ",vx[0],vy[0]); } } int main() { while(scanf("%d%d",&N,&C)!=EOF){ for(int i=0;i<N;i++){ scanf("%d",&L[i]); } for(int i=0;i<C;i++){ scanf("%d%d",&S[i],&A[i]); } solve(); } return 0; }