Crane POJ 2991(线段树+计算几何)

原题

题目链接

题目分析

本题可以用线段树来做.线段树的每个区间维护的值如下.(1)该区间的第一段竖直放置时,从该区间头端指向尾端的向量.(2)拼接两个子区间(如果有子区间的话)时,右儿子需要旋转的角度.这里说明一下,当一个子区间被修改时,如果它是父区间的右儿子,则父区间维护的角度不用变,如果它是父区间的左儿子,则父区间维护的角度需要累加旋转角度.当然该子区间也需要累加旋转角度.也就是说当一个线段被旋转之后,编号比它大的线段都需要旋转相同的角度.拼接两个子区间的公式如下:

x0=x1+(x2*cos(ang)-y2*sin(ang));
y0=y1+(y2*cos(ang)+x2*sin(ang));

其中(x0,y0)是当前区间维护的向量,(x1,y1)是左儿子向量,(x2,y2)是右二子向量,ang是当前区间维护的角度.x1,y1后面的表达式由右儿子向量旋转得出.

还有注意线段树维护的是旋转角度(即改变量),输入的时候不能直接输入题目给的数据,得保留上一次的角度,做差之后才能得到旋转角度.

代码

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 typedef unsigned long long ULL;
 7 typedef long long LL;
 8 typedef long double LB;
 9 const int INF_INT=0x3f3f3f3f;
10 const LL INF_LL=0x3f3f3f3f3f3f3f3f;
11 
12 const double pi=acos(-1.0);
13 
14 typedef struct{int l,r;double x,y,ang;} Node;
15 Node tree[4*10000];
16 double pre[20000];
17 
18 void build(int k,int l,int r)
19 {
20     tree[k].l=l,tree[k].r=r,tree[k].ang=0,tree[k].x=0;
21     if(l==r)
22     {
23         scanf("%lf",&tree[k].y);
24         return ;
25     }
26     int mid=(l+r)/2;
27     build(2*k+1,l,mid);build(2*k+2,mid+1,r);
28     tree[k].y=tree[2*k+1].y+tree[2*k+2].y;
29 }
30 
31 void modify(int k,int s,double ang) //修改函数
32 {
33     int mid=(tree[k].l+tree[k].r)/2; //区间的拼接位置位于mid
34 
35     if(s<mid) modify(2*k+1,s,ang),tree[k].ang+=ang;
36     else if(s>mid) modify(2*k+2,s,ang);
37     else tree[k].ang+=ang;
38 
39     tree[k].x=tree[2*k+1].x+(tree[2*k+2].x*cos(tree[k].ang)-tree[2*k+2].y*sin(tree[k].ang));
40     tree[k].y=tree[2*k+1].y+(tree[2*k+2].y*cos(tree[k].ang)+tree[2*k+2].x*sin(tree[k].ang));
41 }
42 
43 int main()
44 {
45 //    freopen("testdata.in","r",stdin);
46 //  freopen("std.out","w",stdout);
47     int N,C;
48     while(cin>>N&&cin>>C)
49     {
50         for(int i=1;i<=N;i++) pre[i]=pi;
51         build(0,1,N);
52         for(int i=0;i<C;i++)
53         {
54             int s,ang;
55             scanf("%d %d",&s,&ang);
56             double t=pi*ang/180; //输入处理,转化为弧度制并求出旋转角度
57             modify(0,s,t-pre[s]);
58             pre[s]=t;
59             printf("%.2f %.2f\n",tree[0].x,tree[0].y);
60         }
61         cout<<endl;
62     }
63     return 0;
64 }

 

posted @ 2019-10-30 15:08  VBL  阅读(159)  评论(0编辑  收藏  举报