pku2991 Crane 线段树的好题

pku2991 Crane 线段树的好题

简述题意:
一堆竖直依次排列,端点处连接起来。现在给出这样一种操作,将第i个杆子和第i+1个杆子直接的角度调整为180+degree,当然,i+1个杆子以后的杆子连着它一起转动。求最后一个杆子的坐标
可以这样设置线段树的域
1  struct
2  {
3       int  s,e;
4       double  x,y;
5       int  turn;
6  }st[N];
turn代表当前线段 整体旋转过的角度
维护策略可以这样写:用到了坐标的旋转变换矩阵:
|cosx -sinx |
|sinx  cosx|
 1  inline  void  change( double   & x, double   & y, double  turn)
 2  {
 3       double  tx = x,ty = y;
 4      x = cos(turn) * tx - sin(turn) * ty;
 5      y = sin(turn) * tx + cos(turn) * ty;
 6  }
 7  inline  void  update( int  pos, int  add)
 8  {
 9      st[pos].turn = (st[pos].turn + add) % 360 ;
10      change(st[pos].x,st[pos].y,degree(add % 360 ));
11  }
其他标记下移什么的和普通线段树一样,就不赘述了,贴代码
 1 # include  < cstdio >
 2 # include  < cmath >
 3 using   namespace  std;
 4 const   int  N = 50000 ;
 5 const   double  eps = 1e - 6 ;
 6 # define degree(a) ((a) / 180.0 * 3.141592653 )
 7 struct
 8 {
 9    int s,e;
10    double x,y;
11    int turn;
12}
st[N];
13 int  len[N];
14 inline  void  change( double   & x, double   & y, double  turn)
15 {
16    double tx=x,ty=y;
17    x=cos(turn)*tx-sin(turn)*ty;
18    y=sin(turn)*tx+cos(turn)*ty;
19}

20 inline  void  update( int  pos, int  add)
21 {
22    st[pos].turn=(st[pos].turn+add)%360;
23    change(st[pos].x,st[pos].y,degree(add%360));
24}

25 void  init( int  s, int  e, int  pos = 1 )
26 {
27    st[pos].s=s;
28    st[pos].e=e;
29    st[pos].turn=0;
30    if(e==s+1)
31        st[pos].y=len[s],st[pos].x=0;
32    else
33    {
34        init(s,(s+e)>>1,pos<<1);
35        init((s+e)>>1,e,(pos<<1)+1);
36        st[pos].y=st[pos<<1].y+st[(pos<<1)+1].y;
37        st[pos].x=0;
38    }

39}

40 int   get ( int  target, int  pos = 1 )
41 {
42    if(st[pos].e==st[pos].s+1return st[pos].turn;
43    else if(target<((st[pos].s+st[pos].e)>>1)) return st[pos].turn+get(target,pos<<1);
44    else return st[pos].turn+get(target,(pos<<1)+1);
45}

46
47 void  insert( int  s, int  e, int  add, int  pos = 1 )
48 {
49    if(s==st[pos].s&&e==st[pos].e)
50        update(pos,add);
51    else
52    {
53        if(st[pos].turn)
54        {
55            update(pos<<1,st[pos].turn);
56            update((pos<<1)+1,st[pos].turn);
57            st[pos].turn=0;
58        }

59        if(e<=(st[pos].s+st[pos].e)>>1)
60            insert(s,e,add,pos<<1);
61        else if(s>=(st[pos].s+st[pos].e)>>1)
62            insert(s,e,add,(pos<<1)+1);
63        else
64        {
65            insert(s,(st[pos].s+st[pos].e)>>1,add,pos<<1);
66            insert((st[pos].s+st[pos].e)>>1,e,add,(pos<<1)+1);
67        }

68        st[pos].x=st[pos<<1].x+st[(pos<<1)+1].x;
69        st[pos].y=st[pos<<1].y+st[(pos<<1)+1].y;
70    }

71}

72 int  main()
73 {
74    int n,c,pos,turn,d1,d2;
75    while(scanf("%d%d",&n,&c)!=EOF)
76    {
77        for(int i=1;i<=n;i++)
78            scanf("%d",len+i);
79        init(1,n+1);
80        while(c--)
81        {
82            scanf("%d%d",&pos,&turn);
83            d1=get(pos++);
84            d2=get(pos);
85            insert(pos,n+1,turn-180-d2+d1);
86            printf("%.2f %.2f\n",st[1].x+eps,st[1].y+eps);
87        }

88    }

89    return 0;
90}

你可能感兴趣的:(pku2991 Crane 线段树的好题)