題目鏈接:http://poj.org/problem?id=2991
題目意思:這是一個n結棍,現在沿y軸放置,從(0,l1)爲第0條邊,(l1, l2)爲第1條邊……(l(n-1),l(n))爲第n-1條邊,操作說明,把第k條邊沿順時針方向旋轉a度(第k+1……n跟着第k條邊一起旋轉),問題:求每次操作以後這個n結棍的末端的座標
算法:線段樹,三角運算
思路:把n結棍每節的長度保存在每個線段樹的節點上,如果k旋轉a度,那麼把(k,n)每個節點全部都加上一個角度,通過三角運算得到這個節點(線段)沿x軸,沿y軸的長度,統計每個節點(線段)的數據,把它彙總到root節點,就可以得到n結棍末端的座標了。
#include"cstdio"
#include"cstring"
#include"math.h"
using namespace std;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define mid int m = (r+l) >> 1
double sx[234567 << 2];
double sy[223232 << 2];
int sd[232323 << 2];
int angle[232323 << 2];
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 ;
}
mid ;
build(lson);
build(rson);
PushUp(rt);
}
void ff(int rt, int sd)
{
double dd = (sd) * asin(1.0) / 90;
double x = sx[rt] * cos(dd) - sy[rt] * sin(dd);
double y = sx[rt] * sin(dd) + sy[rt] * cos(dd);
sx[rt] = x;
sy[rt] = y;
}
void PushDown(int rt)
{
if(sd[rt] != 0)
{
ff(rt << 1, sd[rt]);
ff(rt << 1 | 1, sd[rt]);
sd[rt << 1] += sd[rt] ; sd[rt << 1 | 1] += sd[rt];
sd[rt] = 0;
}
}
void update(int a, int ang, int l, int r, int rt)
{
if(a < l)
{
ff(rt, ang);
sd[rt] += ang;
return ;
}
mid ;
PushDown(rt);
if(a < m)
update(a, ang, lson);
update(a, ang, rson);
PushUp(rt);
}
int main()
{
int n, m;
int first =1;
while(scanf("%d%d", &n, &m) != EOF)
{
if(first)
first = 0;
else
printf("\n");
int i;
for(i = 1; i <= n; i ++)
angle[i] = 180;
build(1, n, 1);
for(i = 1; i <= m; i ++)
{
int a, b;
scanf("%d%d", &a, &b);
update(a, b-angle[a], 1, n, 1);
angle[a] = b;
printf("%.2lf %.2lf\n",fabs(sx[1])<1e-8?0:sx[1],fabs(sy[1])<1e-8?0:sy[1]);
}
}
return 0;
}