BZOJ 4552 [Tjoi2016&Heoi2016]排序 线段树的分裂和合并
https://www.lydsy.com/JudgeOnline/problem.php?id=4552
https://blog.csdn.net/zawedx/article/details/51818475
区间排序,这道题需要写两个线段树还要维护一个链表,有些细节,对我目前的代码能力来说有点算是码农题,但是理解思路之后调试起来出乎意料地简单。
这个写法的复杂度据说是nlogn的,我也不是很会算,反正能过就行(bushi)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define LL long long
#define lc x*2
#define rc x*2+1
#define mid (l+r)/2
const int maxn=;
const int maxm=;
int n,m;
struct sgtree{
int rn[maxm];
void updata(int x){rn[x]=(rn[rc]?rn[rc]:rn[lc]);}
void ins(int x,int l,int r,int k,int v){
if(l==r){rn[x]=v;return;}
if(k>mid)ins(rc,mid+,r,k,v);
else ins(lc,l,mid,k,v);
updata(x);
}
int ask(int x,int l,int r,int k){
if(!rn[x])return ;
if(l==r)return rn[x];
int zz=;
if(mid<k)zz=ask(rc,mid+,r,k);
if(zz)return zz;
if(mid<=k)return rn[lc];
else return ask(lc,l,mid,k);
}
}e;
struct nod{ int l,r,tp,nxt; }c[maxm];
struct node{ int l,r,sum; }t[maxm];
queue<int>q;
inline int newp(){
int z=q.front();q.pop();
return z;
}
inline void delp(int x){
q.push(x);t[x]=t[];
}
void build(int x,int l,int r,int k){
t[x].sum=;
if(l==r)return;
if(k>mid)build(t[x].r=newp(),mid+,r,k);
else build(t[x].l=newp(),l,mid,k);
}
int mmerg(int x,int y){
if((!x)||(!y))return x+y;
t[x].l=mmerg(t[x].l,t[y].l);
t[x].r=mmerg(t[x].r,t[y].r);
t[x].sum=t[x].sum+t[y].sum;
delp(y); return x;
}
void mspli(int x,int y,int k){
int z=t[t[x].l].sum;
if(z<k)mspli(t[x].r,t[y].r=newp(),k-z);else swap(t[x].r,t[y].r);
if(z>k)mspli(t[x].l,t[y].l=newp(),k);
t[y].sum=t[x].sum-k;
t[x].sum=k;
}
int mask(int x,int l,int r,int k){
if(l==r)return l;
int z=t[t[x].l].sum;
if(k>z)return mask(t[x].r,mid+,r,k-z);
else return mask(t[x].l,l,mid,k);
}
int main(){
int x,v,op,l,r;
for(int i=;i<=maxm-;++i)q.push(i);
scanf("%d%d",&n,&m);
for(int i=,las=maxm-;i<=n;++i,las=x){
scanf("%d",&v);
c[las].nxt=x=newp();
c[x]=(nod){i,i,,};
e.ins(,,n,i,x);build(x,,n,v);
}
for(int i=;i<=m;++i){
scanf("%d%d%d",&op,&l,&r);
/*for(x=1;x<=n;++x){
int w=e.ask(1,1,n,x);
//cout<<w<<' ';
if(c[w].tp)printf("%d ",mask(w,1,n,c[w].r-x+1));
else printf("%d ",mask(w,1,n,x-c[w].l+1));
}printf("\n");*/
int lef=e.ask(,,n,l),rig,now,nxt;
if(l==c[lef].l){
rig=newp();
swap(t[rig],t[lef]); swap(c[rig],c[lef]);
c[now=lef]=(nod){l,r,op,rig};
}
else{
c[now=newp()]=(nod){l,r,op,rig=newp()};
if(!c[lef].tp) mspli(lef,rig,l-c[lef].l);
else {mspli(lef,rig,c[lef].r-l+);swap(t[lef],t[rig]);}
c[rig]=c[lef];c[rig].l=l;
c[lef].r=l-;c[lef].nxt=now;
}
for(nxt=rig;nxt&&r>=c[nxt].r;){
//cout<<t[nxt].sum<<endl;
mmerg(now,nxt);e.ins(,,n,c[nxt].l,);
int qq=nxt;nxt=c[nxt].nxt;c[qq]=c[];
}
c[now].nxt=nxt;
if(nxt!=&&c[nxt].l<=r){
e.ins(,,n,c[nxt].l,);
int zz=newp();
if(!c[nxt].tp) {mspli(nxt,zz,r-c[nxt].l+);swap(t[nxt],t[zz]);}
else mspli(nxt,zz,c[nxt].r-r);
mmerg(now,zz);
c[nxt].l=r+;
e.ins(,,n,r+,nxt);
}
e.ins(,,n,l,now);
}
/*for(x=1;x<=n;++x){
int w=e.ask(1,1,n,x);
//cout<<w<<' ';
if(c[w].tp)printf("%d ",mask(w,1,n,c[w].r-x+1));
else printf("%d ",mask(w,1,n,x-c[w].l+1));
}printf("\n");*/
scanf("%d",&x);
int w=e.ask(,,n,x);
if(c[w].tp)printf("%d\n",mask(w,,n,c[w].r-x+));
else printf("%d\n",mask(w,,n,x-c[w].l+));
return ;
}
BZOJ 4552 [Tjoi2016&Heoi2016]排序 线段树的分裂和合并的更多相关文章
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 线段树 二分
目录 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 update 10.6 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 /* //fang zhi ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案
听说是BC原题. 好题,二分答案变成01序列,就可以方便的用线段树维护了. 然后就是区间查询和覆盖了. #include <map> #include <cmath> #inc ...
- BZOJ 4552: [Tjoi2016&Heoi2016]排序
4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 579 Solved: 322[Sub ...
- bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 线段树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意: 给你一个1-n的全排列,m次操作,操作由两种:1.将[l,r]升序排序,2 ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树
题目链接 题面 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- bzoj 4552: [Tjoi2016&Heoi2016]排序【二分+线段树】
二分值mid,然后把>=mid的赋值为1,其他赋值为0,每次排序就是算出区间内01的个数,然后分别把0和1放到连续的一段内,这些都可以用线段树来维护 二分的判断条件是操作完之后q位置上是否为1 ...
- BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- bzoj 4552 [Tjoi2016&Heoi2016]排序——二分答案
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成 ...
随机推荐
- JS判断页面是否出现滚动条
今天无聊,帮一个网友解决一个很无聊的问题,用JS判断页面是否出现滚动条,在网上看了一些代码,经过验证并不起作用,下面是在网上搜索到的代码: 当可视区域小于页面的实际高度时,判定为出现滚动条,即: if ...
- 首次使用Vue开发
1.首先在页面上添加如下的代码 var app = new Vue({ el: '#signupForm', data: { UserName: '', PWD: '' } }); 2.在下面添加ht ...
- python中argparse模块用法实例详解
python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...
- Linux内存管理4---虚拟地址空间管理
1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...
- Git学习笔记一《版本控制之道-使用Git》
1.在Windows中安装完git后,需要进行一下配置:$ git config --global user.name "zhangliang"$ git config --glo ...
- Ex3_15 判断图是否是一个强连通分量 判断点是否在汇点强连通分量中_十一次作业
(a) 可以用图中的每一个顶点表示街道中的每个十字路口,由于街道都是单行的,所以图是有向图,若从一个十字路口都有一条合法的路线到另一个十字路口,则图是一个强连通图.即要验证的是图是否是一个强连通图. ...
- SKlearn库学习曲线
思想: # 1.现将所有样本用交叉验证方法或者(随机抽样方法) 得到 K对 训练集-验证集# 2.依次对K个训练集,拿出数量不断增加的子集如m个,并在这些K*m个子集上训练模型.# 3.依次在对应训练 ...
- xcode 8 清除无用的打印
OS_ACTIVITY_MODE disable 虽然模拟器这样写能屏蔽掉无用的打印,但是在真机测试的时候什么都不会打印 Nslog 也打印不出来 , 这时候就要点掉 OS_ACTIVIT ...
- Laravel API 限速异常 HTTPException Too Many Attemps
最近线上 Laravel 错误日志发现了一个异常 HTTPException Too Many Attemps 而我一个同事在本地开发的过程中也频繁遇到这个异常.测试环境:Laravel 5.5. 网 ...
- hdu5178 尺取
会爆int /* 给定数轴上一些点对,问有多少点对之间的距离差不超过k 点对排序后尺取法:枚举每个左边界,找到一个右边界使得 */ #include<bits/stdc++.h> #def ...