POJ 2991 Crane (线段树 维护旋转的向量和)
来源:互联网 发布:数学矩阵的用途 编辑:程序博客网 时间:2024/06/08 14:39
题目大意:
就是多个木棍初始摆在y轴上相邻的木棍间有连接着他们的东西, 相当于关节
然后每次操作旋转某个关节, 求旋转后的端点的坐标
大致思路:
首先将所有的木棍拆成多个向量, 那么考虑到向量的和v1 + v2 + ... + vk即为顶点的坐标, 并且多个向量的和旋转得到的角, 和这所有的向量都旋转同样的角再求和得到的向量是同样的
也就是说向量的旋转的时机不影响加法运算于是可以用线段树维护一个向量的数组, 每次区间更新, 利用懒惰标记, 然后逆时针旋转的话有旋转的公式可以很快确定
对于每次询问直接求所有向量的和就可以了, 总体复杂度O(nlogn)
代码如下:
Result : Accepted Memory : 1168 KB Time : 844 ms
/* * Author: Gatevin * Created Time: 2015/8/17 22:49:05 * File Name: Sakura_Chiyo.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define maxn 10010int n, len[maxn];const double PI = acos(-1.0);struct Segment_Tree{ #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 pair<double, double> p[maxn << 2];//向量 double theta[maxn << 2]; void pushUp(int rt) { p[rt].first = p[rt << 1].first + p[rt << 1 | 1].first; p[rt].second = p[rt << 1].second + p[rt << 1 | 1].second; return; } void pushDown(int rt) { if(theta[rt]) { theta[rt << 1] += theta[rt]; theta[rt << 1 | 1] += theta[rt]; p[rt << 1] = make_pair(p[rt << 1].first*cos(theta[rt]) - p[rt << 1].second*sin(theta[rt]), p[rt << 1].first*sin(theta[rt]) + p[rt << 1].second*cos(theta[rt])); p[rt << 1 | 1] = make_pair(p[rt << 1 | 1].first*cos(theta[rt]) - p[rt << 1 | 1].second*sin(theta[rt]), p[rt << 1 | 1].first*sin(theta[rt]) + p[rt << 1 | 1].second*cos(theta[rt])); theta[rt] = 0; } return; } void build(int l, int r, int rt) { theta[rt] = 0;//逆时针方向需要的旋转角 if(l == r) { p[rt] = make_pair(0., len[l]*1.); return; } int mid = (l + r) >> 1; build(lson); build(rson); pushUp(rt); } void update(int l, int r, int rt, int L, int R, double angle)//逆时针多旋转angle { if(l >= L && r <= R) { theta[rt] += angle; p[rt] = make_pair(p[rt].first*cos(angle) - p[rt].second*sin(angle), p[rt].first*sin(angle) + p[rt].second*cos(angle)); return; } int mid = (l + r) >> 1; pushDown(rt); if(mid >= L) update(lson, L, R, angle); if(mid + 1 <= R) update(rson, L, R, angle); pushUp(rt); } pair<double, double> query(int l, int r, int rt, int L, int R) { if(l >= L && r <= R) return p[rt]; int mid = (l + r) >> 1; pushDown(rt); pair<double, double> ret = make_pair(0., 0.); pair<double, double> tmp; if(mid >= L) { tmp = query(lson, L, R); ret.first += tmp.first, ret.second += tmp.second; } if(mid + 1 <= R) { tmp = query(rson, L, R); ret.first += tmp.first, ret.second += tmp.second; } return ret; }};Segment_Tree ST;double angle[maxn];int main(){ int n, Q; while(~scanf("%d %d", &n, &Q)) { for(int i = 1; i <= n; i++) { scanf("%d", &len[i]); angle[i] = PI; } ST.build(1, n, 1); int p, an; for(int i = 1; i <= Q; i++) { scanf("%d %d", &p, &an); double change = an/180.*PI - angle[p]; angle[p] = an/180.*PI; ST.update(1, n, 1, p + 1, n, change); pair<double, double> ans = ST.query(1, n, 1, 1, n); printf("%.2f %.2f\n", ans.first, ans.second); } } return 0;}
0 0
- POJ 2991 Crane (线段树 维护旋转的向量和)
- POJ 2991 Crane(线段树:维护向量+计算几何)
- POJ 2991 Crane(线段树·向量旋转)
- poj 2991 Crane(向量旋转+线段树成段更新)
- poj2991 Crane 向量旋转+线段树
- POJ 2991 Crane(线段树+计算几何—更新向量)
- POJ 2991-Crane(线段树-角度旋转)
- POJ 2991 Crane 线段树
- 线段树 POJ 2991Crane
- poj 2991 Crane(线段树)
- POJ 2991 Crane (线段树)
- POJ 2991 Crane 线段树
- 【POJ 2991 Crane】+ 线段树
- POJ2991 Crane(线段树成段更新+向量旋转)
- [poj 2991]Crane[线段树表示向量之和,而非数量]
- poj 2991--Crane(线段树)
- poj 2991 Crane 线段树lazy_tag
- poj 2991 Crane 线段树 几何
- HDOJ-1869-六度分离
- NYOJ 64 鸡兔同笼
- Dynamics AX 报告分页
- leetcode 137: Single Number II
- UVALive 6838 Flipping Parentheses // 线段树 区间修改 最值查询
- POJ 2991 Crane (线段树 维护旋转的向量和)
- [leetcode] 227.Basic Calculator II
- java基本输入输出编程:文本界面的输入与输出
- google C++编程风格指南之头文件的包含顺序
- 闲话js前端框架(1)——从avalonjs的模板说起
- 服务器后台TCP连接存活问题
- gpio 相关中文文档
- 深入浅出之正则表达式(转载)
- 微信公众帐号开发之环境搭建php+nginx+mysql