BZOJ2636: crisis(可持久化线段树)
解题思路:
题目描述是一大坑点,cancel后面是直接加ask或者redo的。
那么就可以愉快地可持久化了。
注意需要支持区间修改,那么就只需要在再次更新这个点的时候将标记储存在新的儿子中。
最后由下至上询问就好了。
代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 typedef double dnt; 6 const double eps=1e-7; 7 struct trnt{ 8 int ls; 9 int rs; 10 double dltx,dlty; 11 double alpha; 12 bool lunked; 13 }tr[3000000]; 14 struct pnt{ 15 double x,y; 16 void insert(void) 17 { 18 scanf("%lf%lf",&x,&y); 19 return ; 20 } 21 }p[100000]; 22 int siz; 23 int cnt; 24 int n,m; 25 char cmd[1000]; 26 int root[1000000]; 27 void move(int spc,double dx,double dy) 28 { 29 tr[spc].dltx+=dx; 30 tr[spc].dlty+=dy; 31 return ; 32 } 33 void patrol(int spc,double beta) 34 { 35 tr[spc].alpha+=beta; 36 double nx,ny,x,y; 37 x=tr[spc].dltx,y=tr[spc].dlty; 38 nx=x*cos(beta)-y*sin(beta); 39 ny=y*cos(beta)+x*sin(beta); 40 tr[spc].dltx=nx; 41 tr[spc].dlty=ny; 42 return ; 43 } 44 void lunk(int spc) 45 { 46 tr[spc].alpha=tr[spc].dltx=tr[spc].dlty=0; 47 tr[spc].lunked=true; 48 return ; 49 } 50 void pushdown(int spc,int lst) 51 { 52 tr[++siz]=tr[tr[lst].ls]; 53 tr[spc].ls=siz; 54 tr[++siz]=tr[tr[lst].rs]; 55 tr[spc].rs=siz; 56 if(tr[spc].lunked) 57 { 58 lunk(tr[spc].ls); 59 lunk(tr[spc].rs); 60 } 61 patrol(tr[spc].ls,tr[spc].alpha); 62 patrol(tr[spc].rs,tr[spc].alpha); 63 move(tr[spc].ls,tr[spc].dltx,tr[spc].dlty); 64 move(tr[spc].rs,tr[spc].dltx,tr[spc].dlty); 65 tr[spc].lunked=false; 66 tr[spc].alpha=tr[spc].dltx=tr[spc].dlty=0; 67 return ; 68 } 69 void build(int l,int r,int &spc) 70 { 71 spc=++siz; 72 if(l==r)return ; 73 int mid=(l+r)>>1; 74 build(l,mid,tr[spc].ls); 75 build(mid+1,r,tr[spc].rs); 76 return ; 77 } 78 void Move(int l,int r,int ll,int rr,int spc,int lst,double dx,double dy) 79 { 80 if(!spc)return ; 81 if(ll>r||l>rr)return ; 82 if(ll<=l&&r<=rr) 83 { 84 move(spc,dx,dy); 85 return ; 86 } 87 int mid=(l+r)>>1; 88 pushdown(spc,lst); 89 Move(l,mid,ll,rr,tr[spc].ls,tr[lst].ls,dx,dy); 90 Move(mid+1,r,ll,rr,tr[spc].rs,tr[lst].rs,dx,dy); 91 return ; 92 } 93 void Patrol(int l,int r,int ll,int rr,int spc,int lst,double beta) 94 { 95 if(!spc)return ; 96 if(ll>r||l>rr)return ; 97 if(ll<=l&&r<=rr) 98 { 99 patrol(spc,beta); 100 return ; 101 } 102 int mid=(l+r)>>1; 103 pushdown(spc,lst); 104 Patrol(l,mid,ll,rr,tr[spc].ls,tr[lst].ls,beta); 105 Patrol(mid+1,r,ll,rr,tr[spc].rs,tr[lst].rs,beta); 106 return ; 107 } 108 void Lunk(int l,int r,int ll,int rr,int spc,int lst) 109 { 110 if(!spc)return ; 111 if(ll>r||l>rr)return ; 112 if(ll<=l&&r<=rr) 113 { 114 lunk(spc); 115 return ; 116 } 117 int mid=(l+r)>>1; 118 pushdown(spc,lst); 119 Lunk(l,mid,ll,rr,tr[spc].ls,tr[lst].ls); 120 Lunk(mid+1,r,ll,rr,tr[spc].rs,tr[lst].rs); 121 return ; 122 } 123 void query(int l,int r,int spc,int pos,double &x,double &y) 124 { 125 if(!spc)return ; 126 if(l>r)return ; 127 int mid=(l+r)>>1; 128 if(pos<=mid)query(l,mid,tr[spc].ls,pos,x,y); 129 else query(mid+1,r,tr[spc].rs,pos,x,y); 130 if(tr[spc].lunked)x=y=0; 131 if(fabs(tr[spc].alpha)>eps) 132 { 133 double nx,ny; 134 nx=x*cos(tr[spc].alpha)-y*sin(tr[spc].alpha); 135 ny=y*cos(tr[spc].alpha)+x*sin(tr[spc].alpha); 136 x=nx,y=ny; 137 } 138 x+=tr[spc].dltx; 139 y+=tr[spc].dlty; 140 return ; 141 } 142 int main() 143 { 144 // freopen("zoo.in","r",stdin); 145 // freopen("zoo.out","w",stdout); 146 scanf("%d",&n); 147 for(int i=1;i<=n;i++)p[i].insert(); 148 scanf("%d",&m); 149 cnt=1; 150 build(1,n,root[cnt]); 151 while(m--) 152 { 153 scanf("%s",cmd+1); 154 if(cmd[1]=='M') 155 { 156 int l,r; 157 scanf("%d%d",&l,&r); 158 if(l>r)std::swap(l,r); 159 double dx,dy; 160 scanf("%lf%lf",&dx,&dy); 161 tr[++siz]=tr[root[cnt]]; 162 root[++cnt]=siz; 163 Move(1,n,l,r,root[cnt],root[cnt-1],dx,dy); 164 } 165 if(cmd[1]=='P') 166 { 167 int l,r; 168 scanf("%d%d",&l,&r); 169 double beta; 170 scanf("%lf",&beta); 171 if(l>r)std::swap(l,r); 172 tr[++siz]=tr[root[cnt]]; 173 root[++cnt]=siz; 174 Patrol(1,n,l,r,root[cnt],root[cnt-1],beta); 175 } 176 if(cmd[1]=='L') 177 { 178 int l,r; 179 scanf("%d%d",&l,&r); 180 if(l>r)std::swap(l,r); 181 tr[++siz]=tr[root[cnt]]; 182 root[++cnt]=siz; 183 Lunk(1,n,l,r,root[cnt],root[cnt-1]); 184 } 185 if(cmd[1]=='C') 186 { 187 int a; 188 scanf("%d",&a); 189 cnt-=a; 190 } 191 if(cmd[1]=='R') 192 { 193 int a; 194 scanf("%d",&a); 195 cnt+=a; 196 } 197 if(cmd[1]=='A') 198 { 199 int pos; 200 scanf("%d",&pos); 201 double x=p[pos].x,y=p[pos].y; 202 query(1,n,root[cnt],pos,x,y); 203 printf("%.6lf %.6lf\n",x,y); 204 } 205 } 206 return 0; 207 }