poj 2991 Crane(向量旋转+线段树成段更新)

Crane
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 1609   Accepted: 416   Special Judge

Description

ACM has bought a new crane (crane -- jeřáb) . The crane consists of n segments of various lengths, connected by flexible joints. The end of the i-th segment is joined to the beginning of the i + 1-th one, for 1 ≤ i < n. The beginning of the first segment is fixed at point with coordinates (0, 0) and its end at point with coordinates (0, w), where w is the length of the first segment. All of the segments lie always in one plane, and the joints allow arbitrary rotation in that plane. After series of unpleasant accidents, it was decided that software that controls the crane must contain a piece of code that constantly checks the position of the end of crane, and stops the crane if a collision should happen. 

Your task is to write a part of this software that determines the position of the end of the n-th segment after each command. The state of the crane is determined by the angles between consecutive segments. Initially, all of the angles are straight, i.e., 180 o. The operator issues commands that change the angle in exactly one joint. 

Input

The input consists of several instances, separated by single empty lines. 

The first line of each instance consists of two integers 1 ≤ n ≤10 000 and c 0 separated by a single space -- the number of segments of the crane and the number of commands. The second line consists of n integers l1,..., ln (1 li 100) separated by single spaces. The length of the i-th segment of the crane is li. The following c lines specify the commands of the operator. Each line describing the command consists of two integers s and a (1 ≤ s < n, 0 ≤ a ≤ 359) separated by a single space -- the order to change the angle between the s-th and the s + 1-th segment to a degrees (the angle is measured counterclockwise from the s-th to the s + 1-th segment).

Output

The output for each instance consists of c lines. The i-th of the lines consists of two rational numbers x and y separated by a single space -- the coordinates of the end of the n-th segment after the i-th command, rounded to two digits after the decimal point. 

The outputs for each two consecutive instances must be separated by a single empty line.

Sample Input

2 1
10 5
1 90

3 2
5 5 5
1 270
2 90

Sample Output

5.00 10.00

-10.00 5.00
-5.00 10.00

Source

CTU Open 2005

题目:http://poj.org/problem?id=2991

题意:给你一个n节组成的起重机,而每两节直接可以旋转,一开始每节都在y轴上,现在对于每次旋转第i与i+1的角度,求末端的坐标。。。

分析:这题挺有趣的一题,它将线段树应用到了计算几何上,首先需要一些计算几何知识:

           1.向量(x,y)则,向量 逆时针 旋转a弧度 后的向量为(cos a *x-sin a*y,sin a*x+cos a*y)

           2.向量的和刚好指向这些向量头尾相连后所指向的地方,也就是把每条线段看做一个向量,那么这项向量的和正好指向末端的坐标

           3.旋转第i与i+1的角度是,i+1及其上的所有向量都旋转了同样的角度

通过上面的知识我们可以把为题转化为线段树来解决,构造一棵线段树,保存向量旋转的角度,向量坐标的和,角度是累计的,每次旋转 i 的时候,就将线段树中 i+1 到 n 的所有角度加上旋转的角度,当然是用延迟标记喽,而每次一个新的旋转角度过来时,直接旋转这个区间,然后再把角度加到延迟标记上,顺序反了就出错了,一开始这样写就wa了。。。向下更新时也是一样,先旋转再更新延迟标志,具体看代码吧。。。精度问题也比较恶心,居然输出 -0.00,每次都转了一下= =

代码:

#include<cstdio>
#include<iostream>
#include<cmath>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int mm=11111;
int sd[mm<<2],degree[mm];
double sx[mm<<2],sy[mm<<2];
void rotate(int rt,int sd)
{
    double d=sd*asin(1.0)/90.0;
    double x=cos(d)*sx[rt]-sin(d)*sy[rt];
    double y=sin(d)*sx[rt]+cos(d)*sy[rt];
    sx[rt]=x,sy[rt]=y;
}
void pushdown(int rt)
{
    rotate(rt<<1,sd[rt]);
    rotate(rt<<1|1,sd[rt]);
    sd[rt<<1]+=sd[rt];
    sd[rt<<1|1]+=sd[rt];
    sd[rt]=0;
}
void pushup(int rt)
{
    sx[rt]=sx[rt<<1]+sx[rt<<1|1];
    sy[rt]=sy[rt<<1]+sy[rt<<1|1];
}
void build(int l,int r,int rt)
{
    sd[rt]=0;
    if(l==r)
    {
        scanf("%lf",&sy[rt]);
        sx[rt]=0;
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void updata(int p,int d,int l,int r,int rt)
{
    if(p<l)
    {
        rotate(rt,d);
        sd[rt]+=d;
        return;
    }
    if(sd[rt])pushdown(rt);
    int m=(l+r)>>1;
    if(p<m)updata(p,d,lson);
    updata(p,d,rson);
    pushup(rt);
}
int main()
{
    int i,j,n,m,flag=0;
    while(~scanf("%d%d",&n,&m))
    {
        if(flag)puts("");else flag=1;
        build(1,n,1);
        for(i=0;i<=n;++i)degree[i]=180;
        while(m--)
        {
            scanf("%d%d",&i,&j);
            updata(i,j-degree[i],1,n,1);
            degree[i]=j;
            printf("%.2lf %.2lf\n",fabs(sx[1])<1e-8?0:sx[1],fabs(sy[1])<1e-8?0:sy[1]);
        }
    }
    return 0;
}


你可能感兴趣的:(command,input,Build,each,output,Numbers)