题目大意:起重机有n节,题目给出要调节的k节,每节调节成x度,求最后底部的起重机的坐标(最顶上的起点为(0,0))。

分析:一开始我看白书,看不懂他那个向量旋转的坐标是怎么来的,翻了很多博客,才发现,是自己数学基础的遗漏(都怪自己高中没好好学T.T),向量旋转涉及到复数的概念和表达。

首先复数表达式z=x+i*y=|z|*(cosx+i*sinx)(i²=-1),假设两个个复数分别为

z1=x1+y1*i=r1*(cos(p1)+i*sin(p1))

z2=x2+y2*i=r2*(cos(p2)+i*sin(p2))

(r1=|z|,r2=|z|)

z1*z2=r1*r2*(cos(p1+p2)+i*sin(p1+p2))

由上面的结果可以知道两个向量乘积可以看作两个模的乘积,两个向量角度相加。

由这结论可以得到一个向量(x,y),乘上旋转p1度模为1的复数(cos(p1)+i*sin(p1))即

(x+y*i)*(cos(p1)+i*sin(p1))=x*cos(p1)-y*sin(p1)+(y*cos(p1)+x*sin(p1))*i

由此可得向量(x,y)旋转p1度后的向量为( x*cos(p1)-y*sin(p1),(y*cos(p1)+x*sin(p1)) )

即x'= x*cos(p1)-y*sin(p1),y'=y*cos(p1)+x*sin(p1)

另外再说明一下,白书的某个节点的的向量表达上为:该点向量坐标=左儿子节点的向量+右儿子节点的向量(旋转的向量)

这题让真的让我收益非凡

下面附上代码

#define debug
#include<stdio.h>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<functional>
#include<iomanip>
#include<map>
#include<set>
#define pb push_back
using namespace std;
typedef long long ll;
pair<ll,ll>PLL;
pair<int,ll>Pil;
const int INF = 0x3f3f3f3f;
const double inf=1e8+100;
const int maxn =(1<<15)-1;
const int N = 1e4+10;
const ll mod=1000007;
const double eps=1e-8;
const double g=10.0;
const double PI=acos(-1.0);
int n,c;
int L[N];
int S[N],A[N];
double vx[maxn],vy[maxn],ang[maxn];
double prv[maxn]; void init(int k,int l,int r) {
ang[k]=vx[k]=0.0;
//
if(r-l==1) {
vy[k]=L[l];
} else {
int chl=2*k+1,chr=2*k+2;
init(chl,l,(r+l)/2);
init(chr,(r+l)/2,r);
vy[k]=vy[chl]+vy[chr];
}
} void change(int s, double a,int v,int l,int r) {
if(s<=l)
return;
else if(s<r) {
int chl=2*v+1,chr=2*v+2;
int m=(r+l)/2;
change(s,a,chl,l,m);
change(s,a,chr,m,r);
if(s<=m)
ang[v]+=a;
double ss=sin(ang[v]),cc=cos(ang[v]);
vx[v]=vx[chl]+(cc*vx[chr]-ss*vy[chr]);
vy[v]=vy[chl]+(ss*vx[chr]+cc*vy[chr]);
}
} void solve() {
int i,j,cnt=0;
while(~scanf("%d%d",&n,&c)) {
if(cnt++){
puts("");
}
for(i=0; i<n; i++) {
// cin>>L[i];
scanf("%d",&L[i]);
}
for(i=0; i<c; i++) {
// cin>>S[i]>>A[i];
scanf("%d%d",&S[i],&A[i]);
}
//
init(0,0,n);
for(i=1; i<n; i++) {
prv[i]=PI;
}
for(i=0; i<c; i++) {
int s=S[i];
double a=A[i]/180.0*PI;
// cout<<s<<" "<<A[i]<<" "<<a<<endl;
change(s,a-prv[s],0,0,n);
prv[s]=a;
// cout<<fixed<<setprecision(2)<<vx[0]<<" "<<vy[0]<<endl;
printf("%.2f %.2f\n",vx[0],vy[0]);
}
}
} int main() {
// ios_base::sync_with_stdio(false);
#ifdef debug
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
// cin.tie(0);
// cout.tie(0);
solve();
return 0;
}

  若有写的好不的地方,欢迎指出

poj2991 Crane(线段树+集合)白书例题的更多相关文章

  1. 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列

    hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...

  2. (中等) POJ 3225 Help with Intervals , 线段树+集合。

    Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While ...

  3. la3523 白书例题 圆桌骑士 双联通分量+二分图

    具体题解看大白书P316 #include <iostream> #include <algorithm> #include <vector> #include & ...

  4. [NYLG-OJ] 77 开灯问题(白书例题)

    #include<stdio.h> int main() { int a[1010]={0}; //储存灯的开闭情况 int n,k,i,j; scanf("%d%d" ...

  5. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  6. 线段树入门详解,洛谷P3372 【模板】线段树 1

    关于线段树: 本随笔参考例题      P3372 [模板]线段树 1 所谓线段树就是把一串数组拆分成一个一个线段形成的一棵树. 比如说像这样的一个数组1,2,3,4,5: 1 ~ 5 /       ...

  7. poj2991 Crane(线段树)

    Description ACM has bought a new crane (crane -- jeřáb) . The crane consists of n segments of variou ...

  8. 《白书》上线段树RMQ的实现

    白书上的线段树RMQ实现,自己重写了一遍: #include <bits/stdc++.h> using namespace std; const int MAXN=1<<17 ...

  9. [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】

    题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...

随机推荐

  1. VS2005、vs2008+WinXPDDK+DDKWizard配置驱动开发环境

    所需软件下载地址如下(均为有效资源链接,速度都比较可以): vs2005:    http://221.224.22.210/downloadsawyer/VS.Net2005简体中文版.rar wi ...

  2. C# md5加密方法

    public static string md5(string str, int code) { if (code == 16) //16位MD5加密(取32位加密的9~25字符) { return ...

  3. LogHelper 日志记录帮助类

    1.LogHelper 日志记录帮助类 using System; using System.Collections.Generic; using System.Linq; using System. ...

  4. ASP.NET Core 2.0 : 六. 举个例子来聊聊它的依赖注入

    本文通过一个维修工与工具库的例子形象的描述一下为什么要用依赖注入.它的工作原理是什么样的, 然后根据这个类比一下ASP.NET Core 中的依赖注入, 从而深刻了解它的使用方法.注意事项以及回收机制 ...

  5. 芝麻HTTP:Ajax结果提取

    以微博为例,接下来用Python来模拟这些Ajax请求,把我发过的微博爬取下来. 1. 分析请求 打开Ajax的XHR过滤器,然后一直滑动页面以加载新的微博内容.可以看到,会不断有Ajax请求发出. ...

  6. Good Bye 2017 D. New Year and Arbitrary Arrangement

    看了别人的题解 首先这题是一个dp dp[i][j] i是当前有多少个a j是当前有多少个ab子序列 dp[i][j] = dp[i+1][j]*Pa + dp[i][i+j]*Pb; i,j 时加一 ...

  7. 使用ASP.NET广告控件的XML语言创建广告链接--ASP.NET

    1.AdRotator广告控件的所有属性都是可选的,XML文件中可以包含如下表所示的属性(XML文件的广告属性).   属性 说明 ImageUrl 要显示的图像的URL  NavigateUrl 单 ...

  8. WPF之DataContext(转)

    WPF之DataContext(转) 有时候不是你不够聪明,而是别人教给你的东西太烂!相信自己! 这是我认为,目前网络上对“DataContext”解释最好的一篇文章,跟大家分享. 原文地址:http ...

  9. Pazera Free Audio Extractor 中文版 - 轻松将视频背景音乐/对话音频提取出来的免费软件

    这个软件是用来提取视频中的音频的,方便快捷.但是有一个问题,就是如果我提取的视频的名字中有不支持的字符(比如泰文)的时候,那么这个就提取不出来.所以如果名字中有不支持的字符的时候就要先改一个名字,然后 ...

  10. 【RMAN】Oracle中如何备份控制文件?备份控制文件的方式有哪几种?

    真题1. 如何备份控制文件?备份控制文件的方式有哪几种? 答案:备份控制文件的方式有多种. ① 备份控制文件可以在线进行: SQL> ALTER DATABASE BACKUP CONTROLF ...