线段树区间更新+向量知识——POJ 2991

对应POJ题目:点击打开链接

Crane

Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

Submit Status

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

题意:有一个吊车由很多个不同长度的线段组成,一开始是一条长直线起点在(0,0),尾节点在(0,sum[n]),每条线段之间的夹角的初始值是180度。然后有一些操作a、 b将第a条线段和a+1之间的夹角变成b度,经过每一次操作都要求出尾节点的坐标。

思路:线段树区间更新;结点值保存该区间的向量及旋转角(注意他给出的不是旋转角)一个区间的向量值=左子区间的向量+右子区间的向量。

求一个向量(x0,y0)逆时针旋转B度后的向量有一个公式:

x1= x0 * cosB - y0 * sinB

y1 = x0 * sinB + y0 * cosB

顺时针就把-B代入:

x1= x0 * cosB + y0 * sinB

y1 = -x0 * sinB + y0 * cosB

还有一点很恶心,就是旋转角的计算;用一个angle[i]数组表示第i段线段跟第i-1段线段的夹角,我这里是计顺时针旋转的,我初始化angle[]为180,故每次更新时,旋转角t=angle[i]-b;   angle[i]=b;

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define ms(x,y) memset(x,y,sizeof(x))
#define eps 1e-6
const int MAXN=10000+10;
const int INF=1<<30;
using namespace std;
double px[MAXN<<2];
double py[MAXN<<2];
int turn[MAXN<<2];
int angle[MAXN];//第i个线段与第i-1个线段的夹角
//const double pi = acos(-1.0);
const double pi = 3.141592653;

void down(int rt)
{
	if(turn[rt]){
		int t=turn[rt];
		turn[rt<<1]+=t;
		turn[rt<<1|1]+=t;
		//左向量旋转t度
		double x=px[rt<<1], y=py[rt<<1];
		px[rt<<1]=x*cos(t*pi/180) + y*sin(t*pi/180);
		py[rt<<1]=-x*sin(t*pi/180) + y*cos(t*pi/180);

		//右向量旋转t度
		x=px[rt<<1|1], y=py[rt<<1|1];
		px[rt<<1|1]=x*cos(t*pi/180) + y*sin(t*pi/180);
		py[rt<<1|1]=-x*sin(t*pi/180) + y*cos(t*pi/180);

		turn[rt]=0;
	}
}

void buildline(int rt, int left, int right)
{
	if(left==right){
		px[rt]=0.0;
		scanf("%lf", &py[rt]);
		return;
	}
	int mid=(left+right)>>1;
	buildline(rt<<1, left, mid);
	buildline(rt<<1|1, mid+1, right);
	px[rt]=px[rt<<1] + px[rt<<1|1];
	py[rt]=py[rt<<1] + py[rt<<1|1];
}

void updata(int rt, int left, int right, int l, int r, int t)
{
	if(left==l && right==r){
		double x=px[rt], y=py[rt];
		px[rt]=x*cos(t*pi/180) + y*sin(t*pi/180);
		py[rt]=-x*sin(t*pi/180) + y*cos(t*pi/180);
		turn[rt]+=t;
		return;
	}
	down(rt);
	int mid=(left+right)>>1;
	if(mid<l) updata(rt<<1|1, mid+1, right, l, r, t);
	else{
		updata(rt<<1, left, mid, l, mid, t);
		updata(rt<<1|1, mid+1, right, mid+1, r, t);
	}
	px[rt]=px[rt<<1] + px[rt<<1|1];
	py[rt]=py[rt<<1] + py[rt<<1|1];
}

int main()
{
	//freopen("in.txt","r",stdin);
	int N,O,cnt=0;
	while(~scanf("%d%d", &N,&O))
	{
		ms(turn,0);
		for(int i=2; i<=N; i++)
			angle[i]=180;
		if(cnt++) printf("\n");
		buildline(1,1,N);
		int a,b;
		while(O--)
		{
			scanf("%d%d", &a,&b);
			a++;
			int t=angle[a]-b;
			angle[a]=b;
			updata(1,1,N,a,N,t);
			printf("%.2lf %.2lf\n", px[1],py[1]);
		}
	}
	return 0;
}
时间: 2024-10-12 19:27:06

线段树区间更新+向量知识——POJ 2991的相关文章

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

线段树 + 区间更新 + 模板 ---- poj 3468

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59798   Accepted: 18237 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 3468 A Simple Problem with Integers (线段树区间更新入门)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 70442   Accepted: 21723 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 2777 Count Color (线段树区间更新)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37647   Accepted: 11315 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

poj 2528 Mayor&#39;s posters 线段树区间更新

Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at al

POJ 2528 Mayor&#39;s posters (离散化+线段树区间更新)

Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for

POJ 2777 &amp;&amp; ZOJ 1610 &amp;&amp;HDU 1698 --线段树--区间更新

直接将这3题 放一起了  今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 -- 区间更新的话 分为 增减 或者 修改 主要就是个 laze 标记 就是延迟更新 对于区间更新的写法 一般是有2种 其一 仔细划分到每个细小的区间    另一 粗略划分 反正 ==我的代码里会给出2种写法 看自己喜好 hdu 1 //线段树 成段更新 ---> 替换 根结点的查询 2 3 #i