题目链接:https://vjudge.net/problem/POJ-2991
知识准备:
1、向量旋转公式:向量(x,y)逆时针旋转角度A,则旋转后的向量为(x*cos A-y*sin A, x*sin A+y*cos A).
详见:https://www.zybang.com/question/143ceaa20d3942f3c6dbe9415dd81d0a.html
2、PI可用这一行代码取得:
const double PI=acos(-1.0);
解题思路:思路来源于:http://www.cnblogs.com/staginner/archive/2012/04/07/2436436.html。
在此处 struct point pt[rt] 是rt对应的向量的坐标。
以结点间的向量为基础建立线段树。
第48行,if()里面的判断条件是个易错点,一开始没有把l-1,所以错了。
这是一道好题,值得重复做。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 const int maxn=10000+3; 9 const double PI=acos(-1.0); 10 int totlen[maxn],len[maxn],degree[maxn]; 11 int rd[maxn<<2]; 12 int n,c; 13 struct point{ 14 double x,y; 15 }pt[maxn<<2]; 16 double getrad(int a){ 17 return (double)a/180*PI; 18 } 19 void Rotate(double &dx,double &dy,double rad){ 20 double x=dx,y=dy; 21 dx=x*cos(rad)-y*sin(rad); 22 dy=x*sin(rad)+y*cos(rad); 23 } 24 void pushup(int rt){ 25 pt[rt].x=pt[rt<<1].x+pt[rt<<1|1].x; 26 pt[rt].y=pt[rt<<1].y+pt[rt<<1|1].y; 27 } 28 void pushdown(int rt){ 29 if(rd[rt]){ 30 double rad=getrad(rd[rt]); 31 rd[rt<<1]+=rd[rt]; 32 rd[rt<<1|1]+=rd[rt]; 33 Rotate(pt[rt<<1].x,pt[rt<<1].y,rad); 34 Rotate(pt[rt<<1|1].x,pt[rt<<1|1].y,rad); 35 rd[rt]=0; 36 } 37 } 38 void build(int l,int r,int rt){ 39 rd[rt]=0; 40 pt[rt].x=0; pt[rt].y=totlen[r]-totlen[l-1]; 41 // printf("build: l = %d, r = %d, pt[%d].x = %lf, pt[%d].y = %lf ",l,r,rt,pt[rt].x,rt,pt[rt].y); 42 if(l==r) return; 43 int m=(l+r)>>1; 44 build(lson); 45 build(rson); 46 } 47 void update(int L,int R,int delta,int l,int r,int rt){ 48 if(L<=l-1&&r<=R){ 49 double rad=getrad(delta); 50 Rotate(pt[rt].x,pt[rt].y,rad); 51 rd[rt]+=delta; 52 // printf("l = %d, r = %d, pt[%d].x = %lf,pt[%d].y = %lf ",l,r,rt,pt[rt].x,rt,pt[rt].y); 53 return; 54 } 55 if(l==r) return; 56 pushdown(rt); 57 int m=(l+r)>>1; 58 if(L<=m) update(L,R,delta,lson); 59 if(m<R) update(L,R,delta,rson); 60 pushup(rt); 61 } 62 int main(){ 63 64 while(scanf("%d%d",&n,&c)==2){ 65 int s,a; 66 for(int i=1;i<=n;i++){ 67 scanf("%d",&len[i]); 68 totlen[i]=totlen[i-1]+len[i]; 69 } 70 build(1,n,1); //_______________________ 71 for(int i=0;i<=n;i++) degree[i]=0; 72 while(c--){ 73 scanf("%d%d",&s,&a); 74 a-=180; 75 int delta=a-degree[s]; 76 degree[s]=a; 77 update(s,n,delta,1,n,1); 78 printf("%.2lf %.2lf ",pt[1].x,pt[1].y); 79 } 80 printf(" "); 81 } 82 return 0; 83 }