线段树 poj 2991
Posted HelloWorld!--By-MJY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树 poj 2991相关的知识,希望对你有一定的参考价值。
我们只要把这些向量求和,最终所指的位置就是终点,因此我们只要维护好向量的区间和就可以了。对于第二个问题,我们可以用一个数组degree[i]表示第i个向量和第i-1一个向量当前的夹角,这样就有了当前的状态,每次读入操作后就会方便的得到相当于进行旋转多少角度的操作了,然后再更新一下degree[i]即可。并且我们每读入一个操作只会影响一个degree[]的值,不会影响到其他的degree[]。
总而言之,我们要把每个线段看成一个向量,并维护这些向量的区间和,同时要实现对区间中每个元素都加上一个值这一操作。
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; #define MAXN 10010 const double pi =acos(-1.0); int z[MAXN],deg[MAXN],re[MAXN<<3]; struct node { int l,r; double x,y; }x[MAXN<<3]; double getrad(int a) { return a*pi/180; } void Build(int l,int r,int a) { x[a].l=l; x[a].r=r; x[a].x=0; x[a].y=z[r]-z[l-1]; re[a]=0; if(l==r) return ; int mid=(l+r)>>1; Build(l,mid,a<<1); Build(mid+1,r,a<<1|1); } void Rotate(double &dx,double &dy,double rad) { double x=dx,y=dy; dx=x*cos(rad)-y*sin(rad); dy=x*sin(rad)+y*cos(rad); } void push_down(int a) { double rad=getrad(re[a]); int ls=a<<1,rs=a<<1|1; if(re[a]) { re[ls]+=re[a]; re[rs]+=re[a]; Rotate(x[ls].x,x[ls].y,rad); Rotate(x[rs].x,x[rs].y,rad); re[a]=0; } } void push_up(int a) { x[a].x=x[a<<1].x+x[a<<1|1].x; x[a].y=x[a<<1].y+x[a<<1|1].y; } void update(int l,int r,int a1,int w,int a) { double rad=getrad(w); if(l==r) { Rotate(x[a].x,x[a].y,rad); return ; } push_down(a); int mid=(l+r)>>1; if(mid<a1) update(mid+1,r,a1,w,a<<1|1); else { update(l,mid,a1,w,a<<1); Rotate(x[a<<1|1].x,x[a<<1|1].y,rad); re[a<<1|1]+=w; } push_up(a); } int main() { int n,m,ca=1; while(scanf("%d%d",&n,&m)!=EOF) { if(ca!=1) printf("\n"); ca++; for(int i=1;i<=n;i++) { scanf("%d",&z[i]); z[i]=z[i-1]+z[i]; } memset(deg,0,sizeof(deg)); Build(1,n,1); for(int i=1;i<=m;i++) { int s,a; scanf("%d%d",&s,&a); s++; a=a-180; int delta=a-deg[s]; deg[s]=a; update(1,n,s,delta,1); printf("%.2lf %.2lf\n",x[1].x,x[1].y); } } return 0; }
以上是关于线段树 poj 2991的主要内容,如果未能解决你的问题,请参考以下文章