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 }

猜你喜欢

转载自www.cnblogs.com/blog-Dr-J/p/10462745.html
今日推荐