線段樹 POJ 2991Crane

題目鏈接:http://poj.org/problem?id=2991

代碼風格:www.notonlysuccess.com


題目意思:這是一個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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章