POJ 2991

题意:

 

直角坐标系上有N条相连线段(序号分别为1,2,3...N

 

最底层线段的起点为原点

每条线段的初始放置状态平行于y轴方向

 

输入每个线段的长度,以及对序号i线段进行的操作角度a

a的含义为使ii+1之间角度为a

 

输出进行给定操作后线段端点的坐标。

 

思路:

 

每次对序号i转动改变的是编号为 1以及 i+1N两个线段集合的位置关系,需要对两者状态进行高效的动态维护。

 

提取出集合中需要维护的参数并列出关系式即可写出对应的线段树算法。


#include <stdio.h>
#include <math.h>
#define MAX_N 10010
#define MAX_C 10010
#define ST_SIZE ((1 << 15) - 1)
#define M_PI 3.1415926

int N, C;
int L[MAX_N];
int S[MAX_C], A[MAX_N];

double vx[ST_SIZE], vy[ST_SIZE]; // position for node
double ang[ST_SIZE];
double prv[MAX_N];

void init(int now, int l, int r)
{
	ang[now] = vx[now] = 0.0;

	if(r - l == 1)
		vy[now] = L[l];
	else
	{
		int chl = 2*now + 1, chr = 2*now + 2;
		int mid = (l+r)/2;
		init(chl, l, mid);
		init(chr, mid, r);
		vy[now] = vy[chl]+vy[chr];
	}
}

void change(int s, double a, int v, int l, int r)
{
	if(s<=l)
		return;
	else if(s < r)
	{
		int chl = v*2+1;
		int chr = v*2+2;
		int m = (l + r)/2;
		change(s, a, chl, l, m);
		change(s, a, chr, m, r);

		if(s <= m)
			ang[v] += a;

		double s = sin(ang[v]), c = cos(ang[v]);
		vx[v] = vx[chl] + (c*vx[chr] - s*vy[chr]);
		vy[v] = vy[chl] + (s*vx[chr] + c*vy[chr]);
	}
}

int main()
{
    int first = 0;
	while(scanf("%d %d", &N, &C) == 2)
	{
	    if(first)
            printf("\n");
        else
            first = 1;
		for (int i = 0; i < N; ++i)
		{
			scanf("%d", &L[i]);
			prv[i] = M_PI;
		}
		init(0, 0, N);

		for (int i = 0; i < C; ++i)
		{
			int s;
			double a;
			scanf("%d %lf", &s, &a);
			a = a/360.0 * 2 * M_PI;
			change(s, a - prv[s], 0, 0, N);
			prv[s] = a;

			printf("%.2f %.2f\n", vx[0], vy[0]);
		}
		}
}

结果是WA,可能哪些细节没有处理好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值