POJ 2991 - Crane
来源:互联网 发布:查重软件免费 编辑:程序博客网 时间:2024/05/19 02:02
Advanced Data Structures :: Segment Tree
Description
有一个机械臂,想象它以直角坐标系的原点为轴,一节连着一节,最末端为机械手。
你可以旋转任意一个关节,改变机械手的位置。
(有点像《cut the rope》中的机械臂?没错,就是那么个玩意)
而现在要做的就正是这么一件事。
告诉你机械臂每节手臂的长度,不停得去操作它(旋转某个关节)。
请求出每次操作之后机械手的位置。
Type
Advanced Data Structures :: Segment Tree
Analysis
刚开始看可能会质疑,很奇怪,这题和线段树有很什么关系。
其实这题是计算几何和线段树的合体。
我们把手臂都各自看成一个向量。
则机械手的位置正好是手臂向量之和。
旋转某个关节,其实就是把关节到机械手之间的手臂向量统统旋转。
由于手臂很多,要每个向量做相同的旋转操作很费时间。
这时候我们就可以想到用线段树的优势正是可以快速地成段更新。
其实和一般的成段更新题目没什么差别,只是我们通常只是成段替换、或者成段增加。
这时候要做的是,对向量成段得做旋转变换。
只要利用旋转变化矩阵即可。
要注意,从第 s 节手臂开始到机械手要旋转的角度,和第 s - 1 节手臂的角度有关。
因此我们还要记录每个手臂的角度,并且去Query得到它们,才能知道我们要旋转的角度。
Solution
#include <cstdio>#include <cmath>#define LSon(x) ((x) << 1)#define RSon(x) ((x) << 1 | 1)const int MAXN = 10002;const int ROOT = 1;const double PI = acos(-1.0);const double EPS = 1e-8;struct Seg { double x, y; int flag; int degree;};void Rotate(Seg& node, int degree);struct SegTree { Seg node[MAXN << 2]; void Update(int pos) { node[pos].x = node[LSon(pos)].x + node[RSon(pos)].x; node[pos].y = node[LSon(pos)].y + node[RSon(pos)].y; } void Build(int l, int r, int pos) { node[pos].x = node[pos].y = 0; node[pos].flag = 0; node[pos].degree = 0; if (l == r) { scanf("%lf", &node[pos].y); return; } int m = l + r >> 1; Build(l, m, LSon(pos)); Build(m + 1, r, RSon(pos)); Update(pos); } void Push(int pos) { Seg& father = node[pos]; Seg& lson = node[LSon(pos)]; Seg& rson = node[RSon(pos)]; if (father.flag) { Rotate(lson, father.flag); Rotate(rson, father.flag); lson.flag += father.flag; rson.flag += father.flag; father.flag = 0; } } void Modify(int l, int r, int pos, int x, int y, int z) { if (x <= l && r <= y) { Rotate(node[pos], z); node[pos].flag += z; return; } Push(pos); int m = l + r >> 1; if (x <= m) Modify(l, m, LSon(pos), x, y, z); if (y > m) Modify(m + 1, r, RSon(pos), x, y, z); Update(pos); } int Query(int l, int r, int pos, int x) { if (l == r) return node[pos].degree; Push(pos); int m = l + r >> 1; if (x <= m) return Query(l, m, LSon(pos), x); else return Query(m + 1, r, RSon(pos), x); }};int n, c;int s, a;SegTree tree;double GetRad(int x);int main() { bool first = true; while (scanf("%d%d", &n, &c) != EOF) { tree.Build(0, n - 1, ROOT); printf("%s", first ? first = false, "" : "\n"); for (int i = 0; i < c; i++) { scanf("%d%d", &s, &a); int degree = tree.Query(0, n - 1, ROOT, s - 1) + 180 + a - tree.Query(0, n - 1, ROOT, s); tree.Modify(0, n - 1, ROOT, s, n - 1, degree); printf("%.2lf %.2lf\n", tree.node[ROOT].x + EPS, tree.node[ROOT].y + EPS); } } return 0;}double GetRad(int x) { return x * PI / 180;}void Rotate(Seg& node, int degree) { double rad = GetRad(degree); double x = node.x; double y = node.y; node.x = x * cos(rad) + y * -sin(rad); node.y = x * sin(rad) + y * cos(rad); node.degree = (node.degree + degree) % 360;}
- poj 2991 Crane
- POJ 2991 - Crane
- POJ 2991 Crane
- poj 2991-Crane
- POJ 2991 Crane
- poj 2991crane
- 挑战 POJ.2991 Crane
- POJ 2991 Crane
- poj 2991 Crane
- POJ 2991:Crane
- POJ 2991 Crane 笔记
- POJ 2991 Crane 线段树
- 线段树 POJ 2991Crane
- poj 2991 Crane(线段树)
- POJ 2991 Crane (线段树)
- POJ 2991 Crane 线段树
- 【POJ 2991 Crane】+ 线段树
- poj crane
- 灰狼汇编视频笔记 上
- X264的调试与移植
- 关于java中的try-catch-finally语句和return
- 大灰狼的汇编视频教程笔记(下)
- C# 读取临时文件夹gtk算法
- POJ 2991 - Crane
- USACO Contact,难题,运算符重载,QuickSort,
- Android中View绘制流程以及invalidate()等相关方法分析
- 财报对比:GREE和DeNA由来已久的竞争
- 使用oprofile查找性能瓶颈
- 夜,小记流水夏日
- Eclipse 中安装ADT出错
- Eclipse Alt+/ 智能提示失效
- 在Eclipse中创建的新项目没有src文件的解决办法