题意:一个值1到n的数组,一种(多次)操作把l到r的区间反转,然后放到数组尾部

题解:裸的splay,用区间合并和区间分割,反转用lazy标记+pushdown就好了

#include<bits/stdc++.h>
#include<ext/rope>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1 using namespace std;
using namespace __gnu_cxx; const double g=10.0,eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f; struct Node{
Node* ch[];
int v;
int s;
int flip;
int cmp(int x)const{
int d = x - ch[]->s;
if(d==)return -;
return d<= ? :;
}
void maintain()
{
s = + ch[]->s + ch[]->s;
}
void pushdown()
{
if(flip)//类似于线段树的lazy标记
{
flip=;
swap(ch[],ch[]);
ch[]->flip = !(ch[]->flip);
ch[]->flip = !(ch[]->flip);
}
}
};
Node* null = new Node();
void Rotate(Node* &o,int d)
{
Node* k = o->ch[d^];
o->ch[d^] = k->ch[d];
k->ch[d] = o;
o->maintain();k->maintain();
o = k;
}
void splay(Node* &o,int k)
{
o->pushdown();
int d = o->cmp(k);
if(d==)k -= o->ch[]->s + ;//利用二叉树性质
if(d!=-)
{
Node* p = o->ch[d];
p->pushdown();
int d2 = p->cmp(k);
int k2 = (d2== ? k:k-p->ch[]->s-);
if(d2!=-)
{
splay(p->ch[d2],k2);
if(d==d2)Rotate(o,d^);
else Rotate(o->ch[d],d);
}
Rotate(o,d^);
}
}
Node* Merge(Node* left,Node* right)
{
splay(left,left->s);//把排名最大的数splay到根
left->ch[] = right;
left->maintain();
return left;
}
void split(Node* o,int k,Node* &left,Node* &right)
{
splay(o,k);//把排名为k的节点splay到根,右侧子树所有节点排名比k大,左侧小
right = o->ch[];
o->ch[] = null;
left = o;
left->maintain();
}
struct SplayTree{
int n;
Node seq[N];
Node* root;
Node* build(int sz)
{
if(sz==)return null;
Node* l=build(sz/);
Node* o=&seq[++n];
o->v=n;
o->ch[]=l;
o->ch[]=build(sz-sz/-);
o->s = o->flip = ;
o->maintain();
return o;
}
void init(int sz)
{
n=;
null->s = ;
root = build(sz);
}
};
vector<int>ans;
void print(Node* o)
{
if(o!=null)
{
o->pushdown();
print(o->ch[]);
ans.pb(o->v);
print(o->ch[]);
}
}
void debug(Node* o)
{
if(o!=null)
{
o->pushdown();
debug(o->ch[]);
cout<<o->v<<endl;
debug(o->ch[]);
}
}
SplayTree ss;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
ss.init(n+);
// debug(ss.root);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
Node *o,*left,*mid,*right;
split(ss.root,a,left,o);//把ab整体右移一位,保证不会出现0
split(o,b-a+,mid,right);
mid->flip^=;
//把left+mid+right变成left+right+mid(fliped)
ss.root = Merge(Merge(left,right),mid);
}
print(ss.root);
for(int i=;i<ans.size();i++)
printf("%d\n",ans[i]-);
return ;
}
/************ ************/

uva11922splay的更多相关文章

随机推荐

  1. Service 事务(JdbcUtils 升级)

    1. DAO 事务 // 在 DAO 中处理事务真是"小菜一碟" public void xxx(){ Connection con = null; try{ con = Jdbc ...

  2. linux下安装mysql问题总结(一)mysqld_safe mysqld from pid file /usr/local/mysql/data/mysql.pid ended

    linux下安装mysql数据库 linux版本:CentOS release 6.8 (Final) mysql版本:mysql-5.7.16-linux-glibc2.5-x86_64.tar.g ...

  3. 我的Android进阶之旅------>adbd cannot run as root in production builds 的解决方法

    今天用adb root命令时候,报了错误:adbd cannot run as root in production builds C:\Documents and Settings\Administ ...

  4. SAP内存、ABAP内存、共享内存的 区别

    区别: (1)SAP内存使用 SET/GET parameters 方法: SET  PARAMETER  ID  ‘MAT’ field P_MATNR. GET  PARAMETER  ID  ‘ ...

  5. HAProxy安装及简单配置

    一.HAProxy简介 代理的作用:web缓存(加速).反向代理.内容路由(根据流量及内容类型等将请求转发至特定服务器).转码器(将后端服务器的内容压缩后传输给client端).缓存的作用:减少冗余内 ...

  6. Linux用户和用户组管理 用户组管理命令

    添加用户组命令:groupadd 命令格式: [root@localhost ~]# groupadd [选项] 组名 选项: 选项 选项说明 -g GID 指定组ID: 修改用户组命令:groupm ...

  7. linux性能调分析及调优

    转:https://blog.csdn.net/luokehua789789/article/details/53007456 Linux 性能分析以及调优介绍 写在前面:计算机要解决的基本问题之一是 ...

  8. imx6q 添加intel PCIE网卡

    TQ_IMX6Q开发板移植rtl8168-PCIE转千兆网卡 一.配置内核选项PCIE总线驱动支持 默认的内核配置可能没有把PCIE的总线驱动编入内核,所以需要确认是否把驱动编译到了内核里面. 配置好 ...

  9. 谷歌浏览器安装jsonview插件方法

    参考https://www.cnblogs.com/whycxb/p/7126116.html,已安装成功.

  10. nodejs实现静态托管

    const express = require("express"); const app = express(); /* 语法1: app.use(express.static( ...