• BZOJ3223 Tyvj 1729 文艺平衡树


    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 

    Input

    第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
    接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 

    Output

    输出一行n个数字,表示原始序列经过m次变换后的结果 

    Sample Input

    5 3

    1 3

    1 3

    1 4

    Sample Output

    4 3 2 1 5

    HINT


    N,M<=100000

    Source

    平衡树

    正解:splay

    解题报告:

      像我这种蒟蒻,居然还不会splay区间翻转。我真弱真的。

      以前懒得学splay是因为每次都有set,偷懒。。。但是碰到这种题目也是gg,所以不得不学一学。

      看了hzwer的代码,还是全都弄懂了。不具体说了,很简单的、、、

      代码如下:

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 100011;
     21 int n,m;
     22 int fa[MAXN],c[MAXN][2],size[MAXN];
     23 int tag[MAXN];
     24 int rt;
     25 //splay的有序按照位置有序,结点存储的是值
     26 
     27 inline int getint()
     28 {
     29        int w=0,q=0;
     30        char c=getchar();
     31        while((c<'0' || c>'9') && c!='-') c=getchar();
     32        if (c=='-')  q=1, c=getchar();
     33        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     34        return q ? -w : w;
     35 }
     36 
     37 inline void update(int now){
     38     int l=c[now][0],r=c[now][1];
     39     size[now]=size[l]+size[r]+1;
     40 }
     41 
     42 inline void pushdown(int now){   
     43     if(tag[now]) {
     44     swap(c[now][0],c[now][1]);//交换,画个图就可以知道
     45     tag[c[now][0]]^=1; tag[c[now][1]]^=1;//标记改变
     46     tag[now]=0;
     47     }
     48 }
     49 
     50 inline void build(int l,int r,int f){
     51     if(l>r) return ;
     52     if(l==r) {
     53     size[l]=1; fa[l]=f;
     54     if(l<f) c[f][0]=l;
     55     else c[f][1]=l;
     56     return ;
     57     }
     58     int mid=(l+r)/2; build(l,mid-1,mid); build(mid+1,r,mid);
     59     fa[mid]=f; if(mid<f) c[f][0]=mid; else c[f][1]=mid;
     60     update(mid);
     61 }
     62 
     63 inline void rotate(int x,int &k){
     64     int y=fa[x],z=fa[y];  int l,r;
     65     if(x==c[y][0]) l=0; else l=1; 
     66     r=l^1;
     67     if(y==k) k=x;
     68     else {
     69     if(c[z][0]==y) c[z][0]=x; 
     70     else c[z][1]=x;
     71     }
     72     fa[x]=z;  fa[y]=x;
     73     fa[c[x][r]]=y; c[y][l]=c[x][r];
     74     c[x][r]=y;
     75     update(y); update(x);//z不需要!!!
     76 }
     77 
     78 inline void splay(int x,int &k){//把x旋到k
     79     int y,z;
     80     while(x!=k) {
     81     y=fa[x]; z=fa[y];
     82     if(y!=k) {
     83         if(c[y][0]==x ^ c[z][0]==y) rotate(x,k);//在不同边时,旋x
     84         else rotate(y,k);//相同边时,旋y
     85     }
     86     rotate(x,k);
     87     }
     88 }
     89 
     90 inline int find(int x,int rank){
     91     pushdown(x);//每次做之前,下传标记
     92     int l=c[x][0],r=c[x][1];
     93     if(size[l]+1==rank) return x;
     94     else if(size[l]>=rank) return find(l,rank);
     95     else return find(r,rank-size[l]-1);//还要减掉根结点那一个点
     96 }
     97 
     98 inline void work(int l,int r){
     99     int zuo=find(rt,l),you=find(rt,r+2);//找到与这个区间相邻的两个结点
    100     splay(zuo,rt); splay(you,c[rt][1]);//把左相邻结点旋到根,右相邻结点旋到根的右子树,则右相邻结点的左子树即所求区间
    101     tag[c[you][0]]^=1;
    102 }
    103 
    104 inline void solve(){
    105     n=getint(); m=getint();
    106     build(1,n+2,0);//加两个虚拟结点
    107     rt=(n+3)/2;
    108 
    109     int l,r;
    110     for(int i=1;i<=m;i++) {
    111     l=getint(),r=getint();
    112     work(l,r);
    113     }
    114     for(int i=2;i<=n+1;i++) {
    115     printf("%d ",find(rt,i)-1);
    116     }
    117 }
    118 
    119 int main()
    120 {
    121   solve();
    122   return 0;
    123 }
  • 相关阅读:
    Jmeter非GUI模式运行脚本
    vmware下 linux如何扩展磁盘空间
    (完美解决方案)Windows Server 2012 R2报错:无法启动此程序,因为计算机中丢失 apimswincrtstdiol110.dll 解决
    Python程序执行性能优化心得
    jmeter中TPS和吞吐量区别与联系
    Python多进程之Pool进程池浅析
    为什么Jmeter 运行时到达持续时间不停止?
    一些在线实用小工具
    笔记20171225
    JMeter 安装 linux平台
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5652454.html
Copyright © 2020-2023  润新知