您的位置:首页 > 其它

POJ 2991 Crane

2015-08-11 23:48 435 查看
题目大意:

有N根棍子首尾相连,每次更改两个棍子之间的夹角,求最后一个点坐标。

解题思路:

因为前面的角度变了后面的角度也会变,所以显然是个线段树。

但是因为涉及到一点几何知识,我这种智障还是想了蛮久的。

#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
#define db double
#define maxn 10010
#define PI acos(-1.0)
#define eps 1e-9
using namespace std;

struct point{
double x,y;
}p[maxn<<2];
int lazy[maxn<<2],angle[maxn];

int max(int x,int y){
if (x>y) return x;
else return y;
}
int min(int x,int y){
if (x<y) return x;
else return y;
}
void work(int a,int rt){
db x=p[rt].x;
db y=p[rt].y;
db ang=PI/180*a;
p[rt].x=cos(ang)*x-sin(ang)*y;
p[rt].y=sin(ang)*x+cos(ang)*y;
}
void pushup(int rt){
p[rt].x=p[rt<<1].x+p[rt<<1|1].x;
p[rt].y=p[rt<<1].y+p[rt<<1|1].y;
}
void pushdown(int rt){
if (lazy[rt]){
work(lazy[rt],rt<<1);
work(lazy[rt],rt<<1|1);
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void build(int l,int r,int rt){
if (l==r){
scanf("%lf",&p[rt].y);
p[rt].x=0;
return;
}
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void update(int a,int L,int R,int l,int r,int rt){
if (L<=l && r<=R){
lazy[rt]+=a;
work(a,rt);
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if (L<=mid) update(a,L,R,l,mid,rt<<1);
if (R>mid) update(a,L,R,mid+1,r,rt<<1|1);
pushup(rt);
}
int main(){
int n,m;
int cnt=0;
while (scanf("%d%d",&n,&m)==2){
if (cnt++) puts("");
build(1,n,1);
for (int i=1;i<=n;i++) angle[i]=180;
memset(lazy,0,sizeof(lazy));
while (m--) {
int s,a;
scanf("%d%d",&s,&a);
int x=(a-angle[s]+360)%360;
update(x,s+1,n,1,n,1);
angle[s]=a;
printf("%.2lf %.2lf\n",p[1].x+eps,p[1].y+eps);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: