HDU3487 play with chain

题目大意:给出1到n的有序数列,现在有两个操作:

1.CUT a b c 把第a到第b个数剪切下来,放到剩下的第c个数的后边。

2.FLIP a b  把第a到第b个数反转。

经过总共m次操作后,求现在的数列。

n,m<300000

分析:典型的splay题。包含的操作即:查找第k大,剪切,插入,反转等操作。

维护size,rev(反转标记)即可。

通过size可以找到第k大,通过rev做懒标记,可以进行反转。

具体说就是,比如要剪切CUT a,b,c,以先把第a-1个节点splay到根的位置,然后把第b+1个节点spaly到根的右儿子的位置,则a到b这一段就刚好是根的右儿子的左子树了,然后把它剪切下来。再把第c节点splay到根的位置,把第c+1个节点splay到根的右儿子的位置,再把刚才剪切的那一段接在根的右儿子的左儿子位置即可。FLIP a b的话,先把第a-1个节点splay到根的位置,把第b+1个节点splay到根的右儿子的位置,然后对根的右儿子的左子树打上懒标记即可。注意:打蓝标记应该是tree[i].rev^=1,而不是tree[i].rev=1。我就是这样wa了一次。

因为splay树的伸展特性,splay树中要增加两个额外的虚拟节点,即头节点和尾节点。初始时把头结点作为根节点,把尾节点作为根的右儿子。有效节点作为根的左儿子的右子树。

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 using namespace std;

  5 #define MAXN 300505

  6 int tot,root,n,m,a,b,c;

  7 char str[10];

  8 struct node

  9 {

 10     int val,fa,sz;

 11     bool rev;

 12     int ch[2];

 13 }tree[MAXN];

 14 void newnode(int &r,int father,int val)

 15 {

 16     tot++;

 17     r=tot;

 18     tree[tot].fa=father;

 19     tree[tot].val=val;

 20 }

 21 void build(int &root,int l,int r,int father)

 22 {

 23     if(l>r)return;

 24     int mid=(l+r)/2;

 25     newnode(root,father,mid);

 26     build(tree[root].ch[0],l,mid-1,root);

 27     build(tree[root].ch[1],mid+1,r,root);

 28     tree[root].sz=tree[tree[root].ch[0]].sz+tree[tree[root].ch[1]].sz+1;

 29     }

 30 void init()

 31 {

 32     tot=root=0;

 33     memset(tree,0,sizeof tree);

 34     newnode(root,0,-1);

 35     newnode(tree[root].ch[1],root,-1);

 36     build(tree[tree[1].ch[1]].ch[0],1,n,tree[1].ch[1]);

 37     tree[tree[1].ch[1]].sz=tree[tree[tree[1].ch[1]].ch[0]].sz+1;

 38     tree[1].sz=tree[tree[1].ch[1]].sz+1;

 39 }

 40 void pd(int &r)

 41 {

 42     if(tree[r].rev==1)

 43     {swap(tree[r].ch[0],tree[r].ch[1]);

 44         tree[tree[r].ch[0]].rev^=1;

 45         tree[tree[r].ch[1]].rev^=1;

 46         tree[r].rev=0;

 47     }

 48     

 49 }

 50 void pu(int &r)

 51 {

 52     tree[r].sz=tree[tree[r].ch[0]].sz+tree[tree[r].ch[1]].sz+1;

 53     }

 54 void rotato(int &r,bool kind)

 55 {

 56     int y=tree[r].fa;

 57     int yy=tree[y].fa;

 58     if(yy)

 59     {

 60         tree[yy].ch[tree[yy].ch[1]==y]=r;

 61         }

 62         tree[r].fa=yy;

 63         tree[tree[r].ch[kind]].fa=y;

 64     tree[y].ch[!kind]=tree[r].ch[kind];

 65         tree[y].fa=r;

 66         tree[r].ch[kind]=y;

 67         pu(y);

 68         pu(r);

 69 }

 70 void splay(int &r,int goal)

 71 {

 72     while(tree[r].fa!=goal)

 73     {

 74         int y=tree[r].fa;

 75         int yy=tree[y].fa;

 76         if(yy==goal)rotato(r,tree[y].ch[0]==r);

 77         else

 78         {

 79             int kind=(tree[y].ch[0]==r);

 80             if(tree[yy].ch[kind]==y)

 81             {

 82                 rotato(r,kind);

 83                 rotato(r,!kind);

 84             }

 85             else

 86             {

 87                 rotato(y,kind);

 88                 rotato(r,kind);

 89             }

 90         }

 91     }

 92     if(goal==0)

 93         root=r;

 94 }

 95 int find(int r,int k)

 96     {

 97     pd(r);

 98     if(tree[tree[r].ch[0]].sz==k-1)

 99         return r;

100     else if(tree[tree[r].ch[0]].sz>k-1)

101         return find(tree[r].ch[0],k);

102         else return find(tree[r].ch[1],k-tree[tree[r].ch[0]].sz-1);

103     }

104     void print(int &r)

105     {

106     pd(r);

107     if(tree[r].ch[0])

108     print(tree[r].ch[0]);    

109         if(tree[r].val!=-1){printf("%d",tree[r].val);if(tot>3)printf(" ");tot--;}

110         if(tree[r].ch[1])

111         print(tree[r].ch[1]);

112     }

113 int main()

114 {

115     

116     while(scanf("%d%d",&n,&m)&&(n>=0&&m>=0))

117     {

118     init();

119     for(int i=0;i<m;i++)

120     {

121         scanf("%s",str);

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

123         {

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

125             int x1=find(root,a);

126             int y1=find(root,b+2);

127             splay(x1,0);

128             splay(y1,root);

129             int t=tree[tree[root].ch[1]].ch[0];

130             tree[tree[root].ch[1]].ch[0]=0;

131             pu(tree[root].ch[1]);

132             pu(root);

133             x1=find(root,c+1);

134             y1=find(root,c+2);

135             splay(x1,0);

136             splay(y1,root);

137             tree[tree[root].ch[1]].ch[0]=t;

138             tree[t].fa=tree[root].ch[1];

139             pu(tree[root].ch[1]);

140             pu(root);

141         }

142         else 

143         {

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

145             int x=find(root,a);

146             int y=find(root,b+2);

147             splay(x,0);

148             splay(y,root);

149             tree[tree[tree[root].ch[1]].ch[0]].rev^=1;

150         }

151     }

152     print(root);

153     printf("\n");

154     }

155 }
View Code

 

你可能感兴趣的:(chain)