Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) E. Robot Arm 线段树
E. Robot Arm
题目连接:
http://www.codeforces.com/contest/618/problem/E
Description
Roger is a robot. He has an arm that is a series of n segments connected to each other. The endpoints of the i-th segment are initially located at points (i - 1, 0) and (i, 0). The endpoint at (i - 1, 0) is colored red and the endpoint at (i, 0) is colored blue for all segments. Thus, the blue endpoint of the i-th segment is touching the red endpoint of the (i + 1)-th segment for all valid i.
Roger can move his arm in two different ways:
He can choose some segment and some value. This is denoted as choosing the segment number i and picking some positive l. This change happens as follows: the red endpoint of segment number i and segments from 1 to i - 1 are all fixed in place. Imagine a ray from the red endpoint to the blue endpoint. The blue endpoint and segments i + 1 through n are translated l units in the direction of this ray.
In this picture, the red point labeled A and segments before A stay in place, while the blue point labeled B and segments after B gets translated.
He can choose a segment and rotate it. This is denoted as choosing the segment number i, and an angle a. The red endpoint of the i-th segment will stay fixed in place. The blue endpoint of that segment and segments i + 1 to n will rotate clockwise by an angle of a degrees around the red endpoint.
In this picture, the red point labeled A and segments before A stay in place, while the blue point labeled B and segments after B get rotated around point A.
Roger will move his arm m times. These transformations are a bit complicated, and Roger easily loses track of where the blue endpoint of the last segment is. Help him compute the coordinates of the blue endpoint of the last segment after applying each operation. Note that these operations are cumulative, and Roger's arm may intersect itself arbitrarily during the moves.
Input
The first line of the input will contain two integers n and m (1 ≤ n, m ≤ 300 000) — the number of segments and the number of operations to perform.
Each of the next m lines contains three integers xi, yi and zi describing a move. If xi = 1, this line describes a move of type 1, where yi denotes the segment number and zi denotes the increase in the length. If xi = 2, this describes a move of type 2, where yi denotes the segment number, and zi denotes the angle in degrees. (1 ≤ xi ≤ 2, 1 ≤ yi ≤ n, 1 ≤ zi ≤ 359)
Output
Print m lines. The i-th line should contain two real values, denoting the coordinates of the blue endpoint of the last segment after applying operations 1, ..., i. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 4.
Namely, let's assume that your answer for a particular value of a coordinate is a and the answer of the jury is b. The checker program will consider your answer correct if for all coordinates.
Sample Input
5 4
1 1 3
2 3 90
2 5 48
1 4 1
Sample Output
8.0000000000 0.0000000000
5.0000000000 -3.0000000000
4.2568551745 -2.6691306064
4.2568551745 -3.6691306064
Hint
题意
有一个机械臂,这个机械臂上面有n个点,i个点和i+1个点通过一条线段相连接
有两个操作:
1 x y,将第x个线段伸长y米
2 x y,将x个线段绕着上一个线段顺时针旋转y°
然后每次询问之后,问你最后那个点的位置在哪儿
题解:
线段树
我们在线段树的每个叶子节点,维护当前这个线段较上一个线段的角度,和当前线段端点的坐标
修改很简单,直接暴力修改这个叶子节点就好了
push_up的时候,就是把两个线段融合成一个线段
这个大概是个初中数学,大概画一画就出来了吧(误
总之就是这样
还有一种做法是矩阵,旋转和延长,其实都是矩阵变换
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+7;
const double pi = acos(-1.0);
typedef double SgTreeDataType;
struct treenode
{
int L , R ;
SgTreeDataType x,y,ang;
};
treenode tree[maxn*4];
inline void push_down(int o)
{
}
inline void push_up(int o)
{
tree[o].x = tree[o*2].x+tree[o*2+1].x*cos(tree[o*2].ang)-tree[o*2+1].y*sin(tree[o*2].ang);
tree[o].y = tree[o*2].y+tree[o*2+1].x*sin(tree[o*2].ang)+tree[o*2+1].y*cos(tree[o*2].ang);
tree[o].ang = tree[o*2].ang+tree[o*2+1].ang;
}
inline void build_tree(int L , int R , int o)
{
tree[o].L = L , tree[o].R = R;
if (L == R)
{
tree[o].x = 1;
tree[o].y = 0;
tree[o].ang = 0;
return;
}
if (R > L)
{
int mid = (L+R) >> 1;
build_tree(L,mid,o*2);
build_tree(mid+1,R,o*2+1);
push_up(o);
}
}
inline void update1(int QL,int QR,SgTreeDataType v,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR)
{
tree[o].x += v * cos(tree[o].ang);
tree[o].y += v * sin(tree[o].ang);
return;
}
else
{
push_down(o);
int mid = (L+R)>>1;
if (QL <= mid) update1(QL,QR,v,o*2);
if (QR > mid) update1(QL,QR,v,o*2+1);
push_up(o);
}
}
inline void update2(int QL,int QR,SgTreeDataType v,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR)
{
double l = sqrt((tree[o].x*tree[o].x)+(tree[o].y*tree[o].y));
tree[o].ang -= v*pi/180.0;
tree[o].x = l * cos(tree[o].ang);
tree[o].y = l * sin(tree[o].ang);
return;
}
else
{
push_down(o);
int mid = (L+R)>>1;
if (QL <= mid) update2(QL,QR,v,o*2);
if (QR > mid) update2(QL,QR,v,o*2+1);
push_up(o);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build_tree(1,n,1);
for(int i=1;i<=m;i++)
{
int op,x;
double y;
scanf("%d%d%lf",&op,&x,&y);
if(op==1)update1(x,x,y,1);
if(op==2)update2(x,x,y,1);
printf("%.12f %.12f\n",tree[1].x,tree[1].y);
}
return 0;
}
Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) E. Robot Arm 线段树的更多相关文章
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) B. Guess the Permutation 水题
B. Guess the Permutation 题目连接: http://www.codeforces.com/contest/618/problem/B Description Bob has a ...
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) A. Slime Combining 水题
A. Slime Combining 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2768 Description Your frien ...
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) F. Double Knapsack 鸽巢原理 构造
F. Double Knapsack 题目连接: http://www.codeforces.com/contest/618/problem/F Description You are given t ...
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined)
现在水平真的不够.只能够做做水题 A. Slime Combining 题意:就是给n个1给你.两个相同的数可以合并成一个数,比如说有两个相同的v,合并后的值就是v+1 思路:直接模拟栈 #inclu ...
- Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)
题目链接 2016 ACM-ICPC EC-Final Problem G 题意 给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...
- Codeforces Round #370 (Div. 2) E. Memory and Casinos (数学&&概率&&线段树)
题目链接: http://codeforces.com/contest/712/problem/E 题目大意: 一条直线上有n格,在第i格有pi的可能性向右走一格,1-pi的可能性向左走一格,有2中操 ...
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 离线+线段树
题目链接: http://codeforces.com/contest/703/problem/D D. Mishka and Interesting sum time limit per test ...
- Codeforces Round #FF (Div. 2)__E. DZY Loves Fibonacci Numbers (CF447) 线段树
http://codeforces.com/contest/447/problem/E 题意: 给定一个数组, m次操作, 1 l r 表示区间修改, 每次 a[i] + Fibonacci[i-l ...
- Codeforces Round #538 (Div. 2) F 欧拉函数 + 区间修改线段树
https://codeforces.com/contest/1114/problem/F 欧拉函数 + 区间更新线段树 题意 对一个序列(n<=4e5,a[i]<=300)两种操作: 1 ...
随机推荐
- 天气api接口
python调用天气api接口: http://www.sojson.com/open/api/weather/json.shtml?city=北京 http://www.sojson.com/blo ...
- OpenRCT2
https://github.com/OpenRCT2/OpenRCT2 https://github.com/LRFLEW/HRM-CCPU https://github.com/LRFLEW/Op ...
- sicily 1036. Crypto Columns
Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description The columnar encryption scheme scram ...
- unbutu下Io language的解释器安装
今晚看Io,然后要安装解释器,然后就记录下来了... 首先去官网下载 http://iolanguage.com 在页面下方的binaries那里找到自己系统对应的版本,我的是x64deb的,本来是下 ...
- 007 Java并发编程:Callable、Future和FutureTask
原文https://www.cnblogs.com/dolphin0520/p/3949310.html Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述 ...
- 获取file中字段,写入到TXT文件中
一下代码省略了很多,哈哈哈 a.txt文件 uid,type,pointx,pointy,name1,9,911233763,543857286,区间测速起点3,9,906371086,5453354 ...
- mac 使用清除废纸篓或彻底删除某文件 附加: smb afp ftp NAS 访问服务器相关
mac 使用清除废纸篓或彻底删除某文件 附加: smb afp ftp NAS 访问服务器相关 mac 下删除文件方法: 1.使用 cleanmymac 使用 cleamymac 的清理 和 逐个 ...
- docker安装(2016-08-25版本)
. 通过命令对系统的版本进行查看 [root@localhost ~]# uname -a [root@localhost ~]# cat /etc/issue --> 如果是6.5之前的版本 ...
- Mysql 数据库学习笔记04 函数
一.创建自定义函数 * 使用自定义函数,可以返回字符串.整型.实数或者其他类型: create [aggregate] function 名称 (参数列表) return type begin //函 ...
- Nginx web proxy NFS服务
1.nginx web 安装 配置 #systemctl stop firewalld #systemctl disabled firewalld #wget -O /etc/yum.repos.d/ ...