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. php中的__call()函数重载

    <?php #调用类中没有的方法时, 会自动调用__call方法重载 #第一个参数是调用时的方法名, 第二个参数为参数组成的数组 class Cat{ public function Hello ...

  2. Low overhead memory space management

    Methods, apparatus, and systems, including computer programs encoded on a computer storage medium, m ...

  3. 终于解决了Linux下运行OCCI程序一直报Error while trying to retrieve text for error ORA-01804错误

    终于解决了Linux下运行OCCI程序一直报Error while trying to retrieve text for error ORA-01804错误 http://blog.csdn.net ...

  4. JS面试题第一弹

    1.javascript的typeof返回哪些数据类型  alert(typeof [1, 2]); //object     alert(typeof 'leipeng'); //string   ...

  5. SQL中char、nchar、varchar、nvarchar、text概述【转】

    1. char char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符. 2. nchar ...

  6. docker基于本地模版导入创建镜像

    /* 因为直接去网站拿会下载的慢,所以直接到网站里,对着此包--〉右键--〉复制链接地址 网站地址:https://openvz.org/Download/template/precreated */ ...

  7. ffmpeg安装与配置

    wget http://www.ffmpeg.org/releases/ffmpeg-3.1.tar.gz tar -zxvf ffmpeg-3.1.tar.gz cd ffmpeg-3.1 ./co ...

  8. mui 怎样监听scroll事件的滚动距离

    var scroll = mui('.mui-scroll-wrapper').scroll(); document.querySelector('.mui-scroll-wrapper' ).add ...

  9. 一个大div里面包裹一个小div,里面的小div的点击事件不触发外面的这个大div的点击事件

    一开始上html代码 <div id="div1" style="background: blue;width: 100px; height: 100px;&quo ...

  10. angularjs 微信授权登录 微信支付

    最近做一个项目,用angular 一个单页应用,打算打包成 跨平台移动App 以及在微信里面使用.给大家一个案例 首先,熟悉一下微信授权部分的源代码,如下所示: javascript 前端代码: va ...