hdu 3487 Play with Chain

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487

YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.

FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8

He wants to know what the chain looks like after perform m operations. Could you help him? 
题意:题意比较简单,就给一个数列两种操作:1,CUT a,b,c,在原数列截取区间[a,b](a和b指数列a位置和b位置),然后剩下的数列合并在一起,把截取的区间放在那个数列的c  位置;2,FLIP a b 翻转区间[a,b]。
解法:伸展树+延迟标记。
  1 ///*hdu 3487*/

  2 ///G++ 687ms  C++ 609ms

  3 #include<iostream>

  4 #include<cstdio>

  5 #include<cstring>

  6 #include<cstdlib>

  7 #include<cmath>

  8 #include<algorithm>

  9 #define inf 0x7fffffff

 10 using namespace std;

 11 const int maxn=3*1e6+10;

 12 struct Splay_Tree

 13 {

 14     struct Node

 15     {

 16         Node *ch[2],*pre;       ///节点的左儿子和右儿子,父亲节点

 17         int value,size;         ///节点的值和以此节点为根的子树的节点个数

 18         bool rev;               ///判断是否需要翻转

 19     }*root,*null,*lb,*rb,node[maxn];

 20     int count;

 21     bool flag;

 22     Node *NewNode(int value,Node *father)///插入新节点

 23     {

 24         ///Node *e=node[++count];这样写不行

 25         Node *e=node+(++count);

 26         e->value=value;

 27         e->size=1;

 28         e->pre=father;

 29         e->rev=false;

 30         e->ch[0]=e->ch[1]=null;

 31         return e;

 32     }

 33     void Update(Node *p)///更新节点p的信息

 34     {

 35         if (p==null) return;

 36         p->size=p->ch[0]->size + p->ch[1]->size + 1;

 37     }

 38     void PushDown(Node *x)///向下更新标记

 39     {

 40         if (x==null) return;

 41         if (x->rev)

 42         {

 43             x->rev=false;

 44             Node *t=x->ch[0] ;x->ch[0]=x->ch[1] ;x->ch[1]=t;

 45             x->ch[0]->rev= !x->ch[0]->rev;

 46             x->ch[1]->rev= !x->ch[1]->rev;

 47         }

 48     }

 49     void Rotate(Node *x,bool d)///右旋转:true;左旋转:false

 50     {

 51         Node *y=x->pre;

 52         y->ch[!d]=x->ch[d];

 53         if (x->ch[d]!=null) x->ch[d]->pre=y;

 54         x->pre=y->pre;

 55         if (y->pre!=null)

 56         {

 57             if (y==y->pre->ch[d])

 58                 y->pre->ch[d]=x;

 59             else y->pre->ch[!d]=x;

 60         }

 61         x->ch[d]=y;

 62         y->pre=x;

 63         Update(y);

 64         Update(x);

 65         if (root==y) root=x;

 66     }

 67     void Splay(Node *x,Node *target)///伸展操作

 68     {

 69         PushDown(x);

 70         Node *y;

 71         while (x->pre!=target)

 72         {

 73             y=x->pre;

 74             if (x==y->ch[0])

 75             {

 76                 if (y->pre!=target && y->pre->ch[0]==y)

 77                     Rotate(y,true);

 78                 Rotate(x,true);

 79             }

 80             else

 81             {

 82                 if (y->pre!=target && y->pre->ch[1]==y)

 83                     Rotate(y,false);

 84                 Rotate(x,false);

 85             }

 86         }

 87         Update(x);

 88     }

 89     void Select(int k,Node *y)///选择第k个位置的节点

 90     {

 91         Node *x=root;

 92         PushDown(x);

 93         while (k!=x->ch[0]->size+1)

 94         {

 95             if (k<=x->ch[0]->size)

 96                 x=x->ch[0];

 97             else

 98             {

 99                 k -= x->ch[0]->size+1;

100                 x=x->ch[1];

101             }

102             PushDown(x);

103         }

104         Splay(x,y);

105     }

106     void MakeTree(int l,int r,int *an,Node *p,int side)

107     {

108         if (l>r) return;

109         int mid=(l+r)>>1;

110         Node *x;

111         x=NewNode(an[mid],p);

112         p->ch[side]=x;

113         MakeTree(l,mid-1,an,x,0);

114         MakeTree(mid+1,r,an,x,1);

115         Update(x);

116     }

117     ///****///

118     ///在pos后面插入长度为cnt的区间

119     void Insert(int pos,int cnt,int *an)

120     {

121         Select(pos+1,null);

122         Select(pos+2,root);

123         MakeTree(1,cnt,an,root->ch[1],0);

124         Splay(root->ch[1]->ch[0],null);

125     }

126     ///删除pos后长度为cnt的区间

127     void Delete(int pos,int cnt,int ind)

128     {

129         Node *p1;

130         Select(pos,null);

131         Select(pos+cnt+1,root);

132         p1=root->ch[1]->ch[0];

133         root->ch[1]->ch[0]=null;

134 

135         Splay(root->ch[1],null);

136         Select(ind+1,null);

137         Select(ind+2,root);

138         root->ch[1]->ch[0]=p1;

139         Splay(root->ch[1],null);///注意不是Splay(root->ch[1]->ch[0],null)

140     }

141     ///旋转pos后长度为cnt的区间

142     void Reverse(int pos,int cnt)

143     {

144         Select(pos,null);

145         Select(pos+cnt+1,root);

146         root->ch[1]->ch[0]->rev= !root->ch[1]->ch[0]->rev;

147         Splay(root->ch[1]->ch[0],null);

148     }

149     void Index(int pos)

150     {

151         Select(pos+1,null);

152         printf("%d",root->value);

153     }

154     void Out()///调试程序

155     {

156         flag=false;

157         Print(root);///打印整个区间

158         printf("\n");

159     }

160     void Print(Node *now)///打印区间

161     {

162         if (now==null) return;

163         if (now->ch[0]==null&&now->ch[1]==null)

164         {

165             if (now->value!=inf)

166             {

167                 if (flag) printf(" ");

168                 flag=true;

169                 printf("%d",now->value);

170             }

171             return;

172         }

173         PushDown(now);

174         Print(now->ch[0]);

175         if (now->value!=inf)

176         {

177             if (flag) printf(" ");

178             flag=true;

179             printf("%d",now->value);

180         }

181         Print(now->ch[1]);

182     }

183     void init()

184     {

185         count=-1;

186         null=0;

187         null=NewNode(inf,0);

188         null->size=0;

189         lb=root=NewNode(inf,null);

190         rb=root->ch[1]=NewNode(inf,root);

191         Update(root);

192     }

193 }splay;

194 int an[maxn];

195 int main()

196 {

197     int n,m;

198 

199     char str[5];

200     int a,b,c;

201     while (scanf("%d%d",&n,&m)!=EOF)

202     {

203         if (n<0 && m<0) break;

204         splay.init();

205         for (int i=1 ;i<=n ;i++) an[i]=i;

206         splay.Insert(0,n,an);

207         while (m--)

208         {

209             scanf("%s",str);

210             if (str[0]=='C')

211             {

212                 scanf("%d%d%d",&a,&b,&c);

213                 splay.Delete(a,b-a+1,c);

214             }

215             else

216             {

217                 scanf("%d%d",&a,&b);

218                 splay.Reverse(a,b-a+1);

219             }

220         }

221         splay.Out();

222     }

223     return 0;

224 }

 

你可能感兴趣的:(chain)