今天刚刚看了线段树,以为挺简单,不就就是一个区间的最小值,靠父亲节点来判断~。
谁知,看了后面的一道运用线段树的问题,顿时傻眼了,代码看了好多遍,根本就是 就是 就是啥也不懂呗。。。。还能是神马。然后就是老规矩,看网上题解。。。然而这次居然不灵了,还是没怎么懂,然后,然后,然后就是去洗衣服去了呗,还能干神马。神奇的是,在洗衣服过程中,我居然有点想通了。。。。 有点激动地来跟大家分享一下。
首先明确各种题解中的坐标不是单个棍子首尾2端点各自的坐标,而是在特定的区间内所有棍子合起来的(可以看作一个向量)的坐标。而这个特定区间其实就是 线段树分成的各个区间呗。。。。(一直平分,直到最后是剩下叶节点),而我们学习的线段树的根节点代表整个区域的最小值,是根据其2个儿子节点的数值,比较得来的,如果改变某一叶节点的值,会相应的改变包含其的所有节点的值。同理:在此题中,根节点的坐标就是所有棍子合起来的坐标呗,它的值是根据其2个儿子节点的数值合起来的呗。。。。。然后往下推一直到叶节点。。。而转动某一根棍子,相当于把线段树中的叶节点的值给改变了呗,咱们就要相应地改变包含这根棍子的所有节点(区域)的值。思路就是这样。。。。。
下面代码是书上的。。。。。
#include<stdio.h> #include<math.h> #define M_PI acos(-1.0) #define SIZE 100100 int N,C; int L[20010],S[20010],A[20010]; double vx[SIZE<<2],vy[SIZE<<2],ang[SIZE<<2],prv[10010]; void init(int k,int l,int r) { int chl,chr; ang[k]=vx[k]=0.0; if(r-l==1) vy[k]=L[l]; else { chl=k*2+1;chr=k*2+2; init(chl,l,(l+r)/2); init(chr,(l+r)/2,r); vy[k]=vy[chl]+vy[chr]; } } void change(int s,double a,int v,int l,int r) { int chl,chr,m; double ss,c; if(s<=l) return ; else if(s<r) { chl=v*2+1; chr=v*2+2; m=(l+r)/2; change(s,a,chl,l,m); change(s,a,chr,m,r); if(s<=m) { ang[v]+=a; } ss=sin(ang[v]);c=cos(ang[v]); vx[v]=vx[chl]+(c*vx[chr]-ss*vy[chr]); vy[v]=vy[chl]+(ss*vx[chr]+c*vy[chr]); } } int main(void) { int s,i; double a; while(scanf("%d%d",&N,&C)!=EOF) { for(i=0;i<N;i++) scanf("%d",&L[i]); for(i=0;i<C;i++) scanf("%d%d",&S[i],&A[i]); init(0,0,N); for(i=1;i<N;i++) prv[i]=M_PI; for(i=0;i<C;i++) { s=S[i]; a=A[i]*2*M_PI/360.0; change(s,a-prv[s],0,0,N); prv[s]=a; printf("%.2f %.2f\n",vx[0],vy[0]); } } }
#include<stdio.h> #include<math.h> #define lc p<<1,s,mid #define rc p<<1|1,mid+1,e #define mid ((s+e)>>1) #define N 10005 #define pi acos(-1.0) #define eps 1e-8 double x[N>>2],y[N>>2],rot[N>>2]; double rad[N]; void rotate(double &x,double &y,double r) { double xx=x; x=xx*cos(r)-y*sin(r); y=xx*sin(r)+y*cos(r); } void pushup(int p) { x[p]=x[p<<1]+x[p<<1|1]; y[p]=y[p<<1]+y[p<<1|1]; } void pushdown(int p,int s,int e) { int lp,rp; if(fabs(rot[p])>eps) return ; lp=p<<1;rp=p<<1|1; rot[lp]+=rot[p]; rot[rp]+=rot[p]; rotate(x[lp],y[lp],rot[p]); rotate(x[rp],y[rp],rot[p]); rot[p]=0; } void build(int p,int s,int e) { rot[p]=0; if(s==e) { scanf("%lf",&y[p]); x[p]=0; rad[s]=pi; return ; } build(lc); build(rc); pushup(p); } void update(int p,int s,int e,int l,int r,double v) { if(l<=s&&e<=r) { rot[p]+=v; rotate(x[p],y[p],v); return ; } pushdown(p,s,e); if(l<=mid)update(lc,l,r,v); if(r>mid)update(rc,l,r,v); pushup(p); } int main(void) { int n,m,p,first=1; double r; while(~scanf("%d%d",&n,&m)) { build(1,1,n); while(m--) { scanf("%d%lf",&p,&r); r=r/180.0*pi; update(1,1,n,p+1,n,r-rad[p]); rad[p]=r; printf("%.2lf %.2lf\n",x[1],y[1]); } } }