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>
 3using namespace std;
 4const int N=50000;
 5const double eps=1e-6;
 6# define degree(a) ((a)/180.0*3.141592653)
 7struct
 8{
 9    int s,e;
10    double x,y;
11    int turn;
12}
st[N];
13int len[N];
14inline 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}

20inline 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}

25void 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}

40int 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
47void 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}

72int 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}

posted on 2010-11-03 00:03 yzhw 阅读(228) 评论(0)  编辑 收藏 引用 所属分类: data struct


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年11月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜