Evanyou Blog 彩带

  题目传送门

题目描述
Problem Description
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? 
 
输入格式
Input
There will be multiple test cases in a test data. 
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
Then m lines follow, each line contains one operation. The command is like this:
CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n.
The input ends up with two negative numbers, which should not be processed as a case.
 
输出格式
Output
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
 
样例
Sample Input
8 2
CUT 3 5 4
FLIP 2 6
-1 -1
Sample Output
1 4 3 7 6 2 5 8
 
  分析:
  题目大意就是给你一个数列1,2,3,...n,然后有两种操作,一种是将一段区间取下来再接到另一个位置,另一种是区间反转。
  不难看出这是一道平衡树的题目,题目中的区间反转操作很明显的是Splay,用下放标记的方法很容易实现。再看另一种操作,要求将一段数列截下来然后放入另一段中,这个其实可以旋转以后把要移动的一段直接取下,然后在重新调整平衡树,记录要放入的区间的右端点,再把要放入的区间的左端点作为树根,把截下来的一段直接放上去,再调整,把右端点也接上去就可以了。具体看代码。
 
  Code:
  
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=3e5+7;
int n,m,root,tot;
int cnt,ans[N];
struct Node{
  int ch[2],val,fa;
  int size,mark;
  void add(int x,int father){
    mark=ch[0]=ch[1]=0;
    fa=father;val=x;size=1;}
}t[N];
inline int read()
{
  char ch=getchar();int num=0;bool flag=false;
  while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
  while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
  return flag?-num:num;
}
inline void pushup(int x)
{
  int l=t[x].ch[0],r=t[x].ch[1];
  t[x].size=t[l].size+t[r].size+1;
}
inline void pushdown(int x)
{
  if(t[x].mark){
    t[t[x].ch[0]].mark^=1;
    t[t[x].ch[1]].mark^=1;
    swap(t[x].ch[0],t[x].ch[1]);
    t[x].mark=0;}
}
inline void rotate(int x)
{
  int y=t[x].fa;
  int z=t[y].fa;
  int k=(t[y].ch[1]==x);
  t[z].ch[t[z].ch[1]==y]=x;
  t[x].fa=z;
  t[y].ch[k]=t[x].ch[k^1];
  t[t[x].ch[k^1]].fa=y;
  t[x].ch[k^1]=y;
  t[y].fa=x;
  pushup(y);pushup(x);
}
inline void splay(int x,int tag)
{
  while(t[x].fa!=tag){
    int y=t[x].fa;
    int z=t[y].fa;
    if(z!=tag)
      (t[y].ch[1]==x)^(t[z].ch[1]==y)?
    rotate(x):rotate(y);
    rotate(x);}
  if(tag==0)root=x;
}
inline void insert(int x)
{
  int now=root,fa=0;
  while(now)
    fa=now,now=t[now].ch[x>t[now].val];
  now=++tot;
  if(fa)t[fa].ch[x>t[fa].val]=now;
  t[now].add(x,fa);
  splay(now,0);
}
inline int find(int x)
{
  int now=root;
  while(555){
    pushdown(now);
    if(t[t[now].ch[0]].size>=x)now=t[now].ch[0];
    else if(t[t[now].ch[0]].size+1==x)return now;
    else x-=(t[t[now].ch[0]].size+1),now=t[now].ch[1];
  }
}
inline int getmax(int x)
{
  pushdown(x);
  while(t[x].ch[1]){
    x=t[x].ch[1];
    pushdown(x);}
  return x;
}
inline void merge(int x,int y)
{
  t[x].ch[1]=y;
  t[y].fa=x;
}
inline void flip(int l,int r)
{
  l=find(l),r=find(r+2);
  splay(l,0);splay(r,l);
  t[t[t[root].ch[1]].ch[0]].mark^=1;
}
inline void cut(int x,int y,int z)
{
  int l=find(x),r=find(y+2);
  splay(l,0);splay(r,l);
  int root1=t[t[root].ch[1]].ch[0];
  t[t[root].ch[1]].ch[0]=0;
  pushup(t[root].ch[1]);
  pushup(root);
  int neo=find(z+1);
  splay(neo,0);
  int root2=t[root].ch[1];
  merge(root,root1);
  pushup(root);
  int maxx=getmax(root);
  splay(maxx,0);
  merge(root,root2);
  pushup(root);
}
inline void travel(int now)
{
  pushdown(now);
  if(t[now].ch[0])travel(t[now].ch[0]);
  if(t[now].val>1&&t[now].val<n+2)
    ans[++cnt]=t[now].val-1;
  if(t[now].ch[1])travel(t[now].ch[1]);
}
int main()
{
  while(555){
    n=read();m=read();
    if(n<0||m<0)break;
    root=tot=0;
    for(int i=1;i<=n+2;i++)
      insert(i);
    char opt[5];int x,y,z;
    for(int i=1;i<=m;i++){
      scanf("%s",opt);
      if(opt[0]=='F'){
    x=read();y=read();
    flip(x,y);}
      else{
    x=read();y=read();z=read();
    cut(x,y,z);}
    }
    cnt=0;
    travel(root);
    for(int i=1;i<n;i++)
      printf("%d ",ans[i]);
    printf("%d
",ans[n]);
  }
  return 0;
}
原文地址:https://www.cnblogs.com/cytus/p/8869689.html