1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<stdlib.h> 5 #define N (10010<<2) 6 #define maxn 10000 7 #define lson l,m,rt<<1 8 #define rson m+1,r,rt<<1|1 9 #define pi acos(-1.0) 10 11 int ang[N]; 12 double x[N],y[N],len[maxn+1]; 13 14 void Rotate(int rt,double rad) 15 { 16 double s=x[rt],t=y[rt]; 17 x[rt]=s*cos(rad)-t*sin(rad); 18 y[rt]=s*sin(rad)+t*cos(rad); 19 } 20 21 double getrad(double x) 22 { 23 return x*pi/180.0; 24 } 25 26 void PushDown(int rt) 27 { 28 if(ang[rt]) 29 { 30 ang[rt<<1]+=ang[rt]; 31 ang[rt<<1|1]+=ang[rt]; 32 double rad=getrad(ang[rt]); 33 ang[rt]=0; 34 Rotate(rt<<1,rad); 35 Rotate(rt<<1|1,rad); 36 } 37 } 38 39 void PushUp(int rt) 40 { 41 x[rt]=x[rt<<1]+x[rt<<1|1]; 42 y[rt]=y[rt<<1]+y[rt<<1|1]; 43 } 44 45 void build(int l,int r,int rt) 46 { 47 ang[rt]=0; 48 if(l==r) 49 { 50 x[rt]=0; 51 y[rt]=len[l]; 52 return ; 53 } 54 int m=(l+r)>>1; 55 build(lson); 56 build(rson); 57 PushUp(rt); 58 } 59 60 void update(int p,int del,int l,int r,int rt) 61 { 62 if(l==r) 63 { 64 double rad=getrad(del); 65 Rotate(rt,rad); 66 return; 67 } 68 int m=(l+r)>>1; 69 PushDown(rt); 70 if(p<=m) 71 { 72 double rad=getrad(del); 73 update(p,del,lson); 74 Rotate(rt<<1|1,rad); 75 ang[rt<<1|1]+=del; 76 } 77 else 78 update(p,del,rson); 79 PushUp(rt); 80 } 81 82 int main(void) 83 { 84 int n,q; 85 int flag=0; 86 int index,degree[maxn+1],d; 87 while(~scanf("%d%d",&n,&q)) 88 { 89 memset(degree,0,sizeof(degree)); 90 memset(ang,0,sizeof(ang));/*旋转角度初始化为0,也就是一开始不旋转,这一步也可以放在build函数里面进行,不能遗漏*/ 91 if(flag) puts(""); 92 else flag=1; 93 for(int i=1; i<=n; i++) 94 scanf("%lf",len+i); 95 build(1,n,1); 96 while(q--) 97 { 98 scanf("%d%d",&index,&d); 99 d-=180; 100 index++;/*index要先增加,然后再和degree[intdex]求旋转角度*/ 101 int delta=d-degree[index]; 102 degree[index]=d; 103 update(index,delta,1,n,1); 104 printf("%.2f %.2f\n",x[1],y[1]); 105 } 106 } 107 return 0; 108 }
关于Rotae函数是这样理解的,更新时表示index+1段之后的线段绕index段末端点旋转delta度,x,y分别对应index+1之后的线段在x轴,y轴上投影。
根据x'=x*cos(rad)-y*sin(rad),y'=x*sin(rad)+y*cos(rad)可以将旋转后的投影算出来。