题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487
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 }