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 线段树的更多相关文章

  1. 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 ...

  2. 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 ...

  3. 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 ...

  4. Wunder Fund Round 2016 (Div. 1 + Div. 2 combined)

    现在水平真的不够.只能够做做水题 A. Slime Combining 题意:就是给n个1给你.两个相同的数可以合并成一个数,比如说有两个相同的v,合并后的值就是v+1 思路:直接模拟栈 #inclu ...

  5. Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)

    题目链接  2016 ACM-ICPC EC-Final Problem G 题意  给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...

  6. Codeforces Round #370 (Div. 2) E. Memory and Casinos (数学&&概率&&线段树)

    题目链接: http://codeforces.com/contest/712/problem/E 题目大意: 一条直线上有n格,在第i格有pi的可能性向右走一格,1-pi的可能性向左走一格,有2中操 ...

  7. 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 ...

  8. 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 ...

  9. Codeforces Round #538 (Div. 2) F 欧拉函数 + 区间修改线段树

    https://codeforces.com/contest/1114/problem/F 欧拉函数 + 区间更新线段树 题意 对一个序列(n<=4e5,a[i]<=300)两种操作: 1 ...

随机推荐

  1. (十九)git版本管理软件——搭建git服务器

    创建管理员git 为管理员用户添加sudo权限 生成管理员秘钥 设置管理员git提交账号和邮箱 下载安装gitolite 启动gitolite 添加项目版本库 添加项目成员 项目成员下载项目 gito ...

  2. 【bzoj4373】算术天才⑨与等差数列

    同之前那道由乃题,可以认为由乃题是这题的特殊情况…… 维护方法是同样的,维护区间和,区间平方和即可. 注意特判一个数(其实没有必要) #include<bits/stdc++.h> ; u ...

  3. linux sftp and unix ftp

    sftp 1.功能作用 sftp 是一个交互式文件传输程式.它类似于 ftp, 但它进行加密传输,比FTP有更高的安全性. 2.位置 /usr/bin/sftp 3.格式用法 sftp [-1246C ...

  4. gunicorn 启动无日志

    gunicorn -c gunicorn_info.py info:app 接手整理老项目,发现有个服务迁移后启动不了,也没报错信息 修改gunicorn_info.py里的daemon = not ...

  5. overflow属性在IE6下面失去效果

    自然状态下 overflow的属性设置,本来是超过了一定的长度时会自动产生滚动条,但是在ie6下面失效了. 例如:原来的代码: .code{overflow-x:auto;margin:5px aut ...

  6. MAC 'readonly' option is set (add ! to override)错误解决

    该错误为当前用户没有权限对文件作修改 输入 :w !sudo tee %

  7. C入门之一

    1.stdio.h不要写错成studio.h 2. #include <stdio.h> int main() { /* 我的第一个 C 程序 */ printf("Hello, ...

  8. Nginx配置问题总结

    1.Nginx直接下载解压,有个nginx.exe文件,双击即开启Nginx服务(windows系统下).默认是80端口. 若服务无法启动,考虑以下三方面问题: (1)端口号80是否被占用 (2)防火 ...

  9. 对于mysql加索引,删除索引,添加列,删除列,修改列顺序的最佳办法测试

    1.首先进行数据训的XltraBackup备份,有备无患,切记切记! 2.mysql -uroot -pD******** -- 导出csv文件 use dsideal_db; MariaDB [ds ...

  10. PHP PDO类 单例

    <?php /*//pdo连接信息 $pdo=array("mysql:host=localhost;dbname=demo;charset=utf8","root ...