codevs3243 区间翻转
给出N个数,要求做M次区间翻转(如1 2 3 4变成4 3 2 1),求出最后的序列
第一行一个数N,下一行N个数表示原始序列,在下一行一个数M表示M次翻转,之后的M行每行两个数L,R表示将区间[L,R]翻转。
一行N个数 , 表示最终序列。
4
1 2 3 4
2
1 2
3 4
2 1 4 3
对于30%的数据满足n<=100 , m <= 10000
对于100%的数据满足n <= 150000 , m <= 150000
对于100%的数据满足n为2的幂,且L = i * 2^j + 1 , R = (i + 1) * 2^j
正解:splay
解题报告:
一样的区间翻转,只是我只翻转位置编号,最后对着序列输出就可以了。
//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = ;
int n,m;
int id[MAXN];
int fa[MAXN],c[MAXN][],size[MAXN];
int tag[MAXN];
int rt;
//splay的有序按照位置有序,结点存储的是值 inline int getint()
{
int w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} inline void update(int now){
int l=c[now][],r=c[now][];
size[now]=size[l]+size[r]+;
} inline void pushdown(int now){
if(tag[now]) {
swap(c[now][],c[now][]);//交换,画个图就可以知道
tag[c[now][]]^=; tag[c[now][]]^=;//标记改变
tag[now]=;
}
} inline void build(int l,int r,int f){
if(l>r) return ;
if(l==r) {
size[l]=; fa[l]=f;
if(l<f) c[f][]=l;
else c[f][]=l;
return ;
}
int mid=(l+r)/; build(l,mid-,mid); build(mid+,r,mid);
fa[mid]=f; if(mid<f) c[f][]=mid; else c[f][]=mid;
update(mid);
} inline void rotate(int x,int &k){
int y=fa[x],z=fa[y]; int l,r;
if(x==c[y][]) l=; else l=;
r=l^;
if(y==k) k=x;
else {
if(c[z][]==y) c[z][]=x;
else c[z][]=x;
}
fa[x]=z; fa[y]=x;
fa[c[x][r]]=y; c[y][l]=c[x][r];
c[x][r]=y;
update(y); update(x);//z不需要!!!
} inline void splay(int x,int &k){//把x旋到k
int y,z;
while(x!=k) {
y=fa[x]; z=fa[y];
if(y!=k) {
if(c[y][]==x ^ c[z][]==y) rotate(x,k);//在不同边时,旋x
else rotate(y,k);//相同边时,旋y
}
rotate(x,k);
}
} inline int find(int x,int rank){
pushdown(x);//每次做之前,下传标记
int l=c[x][],r=c[x][];
if(size[l]+==rank) return x;
else if(size[l]>=rank) return find(l,rank);
else return find(r,rank-size[l]-);//还要减掉根结点那一个点
} inline void work(int l,int r){
int zuo=find(rt,l),you=find(rt,r+);//找到与这个区间相邻的两个结点
splay(zuo,rt); splay(you,c[rt][]);//把左相邻结点旋到根,右相邻结点旋到根的右子树,则右相邻结点的左子树即所求区间
tag[c[you][]]^=;
} inline void solve(){
n=getint();
for(int i=;i<=n;i++) id[i]=getint();
build(,n+,);//加两个虚拟结点
rt=(n+)/; int l,r;
m=getint();
for(int i=;i<=m;i++) {
l=getint(),r=getint();
work(l,r);
}
for(int i=;i<=n+;i++) {
printf("%d ",id[find(rt,i)-]);
}
} int main()
{
solve();
return ;
}
codevs3243 区间翻转的更多相关文章
- [BZOJ 3223 & Tyvj 1729]文艺平衡树 & [CodeVS 3243]区间翻转
题目不说了,就是区间翻转 传送门:BZOJ 3223 和 CodeVS 3243 第一道题中是1~n的区间翻转,而第二道题对于每个1~n还有一个附加值 实际上两道题的思路是一样的,第二题把值对应到位置 ...
- WIKIOI 3243 区间翻转
3243 区间翻转 题目描述 Description 给出N个数,要求做M次区间翻转(如1 2 3 4变成4 3 2 1),求出最后的序列 输入描述 Input Description 第一行一个数N ...
- hdu-3487-Play with Chain-(splay 区间翻转,切割,插入)
题意: 区间翻转,切割,插入 // File Name: ACM/HDU/3487.cpp // Author: Zlbing // Created Time: 2013年08月10日 星期六 21时 ...
- hdu-1890-Robotic Sort splay区间翻转
题意: 依次找第i大的数下标pos[i],然后将区间[i,pos[i]]翻转 分析: splay树区间翻转 // File Name: ACM/HDU/1890.cpp // Author: Zlbi ...
- bzoj3223 Tyvj 1729 文艺平衡树(Splay Tree+区间翻转)
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2202 Solved: 1226[Submit][Sta ...
- [置顶] hdu 1890 伸展树区间翻转
题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...
- hdu3397区间覆盖,区间翻转,区间合并,区间求和
调了很久的代码..注意区间翻转和覆盖的操作互相的影响 /* 区间替换操作怎么搞? 应该是加个tag标记 如果整个区间都是0|1,那么把若有tag的话直接set1|0即可,也不用设置tag标记 反之要设 ...
- CODEVS 4655 序列终结者-splay(区间更新、区间翻转、区间最值)
4655 序列终结者 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 网上有许多题,就是给定一个序列,要 ...
- BZOJ4975: [Lydsy1708月赛]区间翻转( 博弈&逆序对)
4975: [Lydsy1708月赛]区间翻转 Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 265 Solved: 140[Submit][Stat ...
随机推荐
- java 21 - 12 IO流的打印流
打印流 字节流打印流 PrintStream 字符打印流 PrintWriter打印流的特点: A:只有写数据的,没有读取数据.只能操作目的地,不能操作数据源.(只能写入数据到文件中,而不能从文件中提 ...
- [解决方案]在Sql Server 2008/2005 数据库还原出现 3154错误
在Sql Server 2008/2005 数据库还原出现 3154错误 解决方法1:不要在数据库名字上点右键选择还原,而要是在根目录“数据库”三个字上点右键选择还原,然后再选择数据库,问题便可以解决 ...
- sed 4个功能
[root@lanny test]# cat test.txt test liyao lanny 经典博文: http://oldboy.blog.51cto.com/2561410/949365 h ...
- C语言 文件操作9--fgetc()和fputc()
//fgetc()和fputc() #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> # ...
- 挖Linux中的古老缩略语
[2005-06-22 15:23][Nigel McFarlane][TechTarget] <<阅读原文>> Unix已经有35年历史了.许多人认为它开始于中世纪,这个中世 ...
- LUA GC 简单测试
function table.count(t) if type(t) ~= "table" then assert(false) return end for k, _ in pa ...
- 如何自定义kindeditor编辑器的工具栏items即去除不必要的工具栏或者保留部分工具栏
kindeditor编辑器的工具栏主要是指编辑器输入框上方的那些可以操作的菜单,默认情况下编辑器是给予了所有的工具栏.针对不同的用户,不同的项目,不同的环境,可能就需要保留部分工具栏.那么我们应该如何 ...
- qrcodeJS生成二维码
后续抽时间自己来整理笔记 http://code.ciaoca.com/javascript/qrcode/
- Vim中split的使用方法
Vim中split的使用方法 一.作用 用split可以显示两个不同的文件:或者同时显示一个文件的两个不同地方:又或者并排比较两个文件.这一切都可以通过分割窗口实现.如下图,左边的两个窗口是mytoo ...
- 每日一SQL-善用DATEADD和DATEDIFF
转自:http://www.dotblogs.com.tw/lastsecret/archive/2010/10/04/18097.aspx 上個星期去Tech-Day聽了幾場有趣的課,其中一堂是楊志 ...