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 ...
随机推荐
- go环境变量及build文件
package main /* windows go环境设置: # 参考:https://blog.csdn.net/quicmous/article/details/80360126 GOROOT ...
- java===java基础学习(5)---文件读取,写入操作
文件的写入读取有很多方法,今天学到的是Scanner和PrintWriter 文件读取 Scanner in = new Scanner(Paths.get("file.txt") ...
- python实战===一键刷屏
#当按键q的时候,自动输入 “大家好!”并回车键发送!from pynput import keyboard from pynput.keyboard import Key, Controller k ...
- vue有关绑定的知识点
一.v-bind绑定class 1.对象的形式 <div :class="{text-danger:true}"></div> 数组形式绑定class &l ...
- linux命令--head
head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 具体使用参考链接: h ...
- [ Python ] set集合及函数的使用
1. set类型 set 和 dict 类似,也是一组 key 的集合,但是不存储 value. 由于 key 不重复,所以,在 set 中, 没有重复的 key 集合是可变类型 (1)集合的创建 ...
- Container With Most Water——双指针
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...
- CentOS7.5安装配置conky(极简)
1.安装epel源 下载地址:http://dl.fedoraproject.org/pub/epel/ 找到epel-release-XXXXXXX.rpm文件,下载解压 rpm -ivh epel ...
- Codeforces 1131 C. Birthday-暴力 (Codeforces Round #541 (Div. 2))
C. Birthday time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...
- NYOJ 228 士兵杀敌(五)【差分标记裸题】
题目链接 所有元素初始值为0才能这么做: ①l--r全加1 a[l]++; a[r+1]--; 求一遍前缀和为元素本身. 求两遍前缀和为元素前缀和. #include<cstdio> #i ...