BZOJ4552: [Tjoi2016Heoi2016]排序
4552: [Tjoi2016&Heoi2016]排序
Time Limit: 60 Sec Memory Limit: 256 MB
Submit: 2554 Solved: 1302
[Submit][Status][Discuss]
Description
Input
Output
输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。
Sample Input
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
Sample Output
HINT
Source
[Submit][Status][Discuss]
题解:线段树合并与分裂模板题???这题有个非常巧妙的二分答案转化为01序列的线段树做法,也相对好写,但多了一层log。然后快一点的做法是先建立N颗权值线段树,动态开点,记录每个区间下节点个数。一段区间排序就是将这段区间合并。但是前后的区间合并会产生交集,从而就需要分裂,就是我们要取出l,r这段区间,在左右两侧的能延伸进来的线段都要分裂。就对于左边来说l所属的那个区间如果左端点小于l那么就要分开,也就是维护一些不相交的线段,且他们的并是1~n,那么之前几个月虽然这类题没碰过但是听到了很多讨论,肯定是用个set啦,就按照右端点排序,二分一下就可以找到一个点所属的线段。然后就像权值线段树那样查找第k个元素就好了。不过因为有递增递减两种序列,那么就是如果是递减就先减右区间,递增先减左区间。以上内容都是我学着这篇代码理解的。http://www.cnblogs.com/Gloid/p/10204585.html
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define ll long long
using namespace std;
const int maxn=1e5+7;
inline ll read()
{ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int n,m;
struct node
{int l,r,num;
}no[maxn*80];
int state[maxn],root[maxn];
struct seg
{int l,r;seg(){};seg(int _l,int _r){l=_l;r=_r;}friend bool operator<(seg a,seg b){return a.r<b.r;}
};
set<seg>st;
int cnt;
void insertt(int &x,int l,int r,int pl)
{if(!x)x=++cnt;no[x].num++;if(l==r)return;int mid=(l+r)>>1;if(pl<=mid)insertt(no[x].l,l,mid,pl);else insertt(no[x].r,mid+1,r,pl);
}
void split(int &x,int &y,int k,int op)
{if(!x)return;y=++cnt;no[y].num=no[x].num-k;no[x].num=k;if(op==0){if(no[no[x].l].num==k){no[y].r=no[x].r;no[x].r=0;return;}else if(no[no[x].l].num>k){no[y].r=no[x].r;no[x].r=0;split(no[x].l,no[y].l,k,op);}else{split(no[x].r,no[y].r,k-no[no[x].l].num,op);}}else{if(no[no[x].r].num==k){no[y].l=no[x].l;no[x].l=0;return;}else if(no[no[x].r].num>k){no[y].l=no[x].l;no[x].l=0;split(no[x].r,no[y].r,k,op);}else{split(no[x].l,no[y].l,k-no[no[x].r].num,op);}}
}
void merge(int &x,int &y,int l,int r)
{if(!x||!y){x|=y;return;}no[x].num+=no[y].num;if(l==r)return;int mid=(l+r)>>1;merge(no[x].l,no[y].l,l,mid);merge(no[x].r,no[y].r,mid+1,r);
}
int query(int x,int l,int r,int pl,int op)
{if(l==r)return l;int mid=(l+r)>>1;//cout<<l<<" "<<r<<endl;if(op==0){if(no[no[x].l].num>=pl)return query(no[x].l,l,mid,pl,op);else return query(no[x].r,mid+1,r,pl-no[no[x].l].num,op);}else{if(no[no[x].r].num>=pl)return query(no[x].r,mid+1,r,pl,op);else return query(no[x].l,l,mid,pl-no[no[x].r].num,op);}
}
set<seg>::iterator it;
int main()
{n=read();m=read();int tmp;for(int i=1;i<=n;i++){tmp=read();insertt(root[i],1,n,tmp);st.insert(seg(i,i));}int op,l,r;while(m--){op=read();l=read();r=read();it=st.lower_bound(seg(l,l));if((*it).l<l){split(root[(*it).l],root[l],l-(*it).l,state[(*it).l]);int L=(*it).l,R=(*it).r;st.erase(it);st.insert(seg(L,l-1));st.insert(seg(l,R));state[l]=state[L];}it=st.lower_bound(seg(r,r));if(it!=st.end()&&(*it).l<=r&&(*it).r>r){split(root[(*it).l],root[r+1],r-(*it).l+1,state[(*it).l]);int L=(*it).l,R=(*it).r;st.erase(it);st.insert(seg(L,r));st.insert(seg(r+1,R));state[r+1]=state[L];}it=st.lower_bound(seg(l,l));it++;while(it!=st.end()&&(*it).r<=r){merge(root[l],root[(*it).l],1,n);it++;}it=st.lower_bound(seg(l,l));while(it!=st.end()&&(*it).r<=r){st.erase(it);it=st.lower_bound(seg(l,l));}st.insert(seg(l,r));state[l]=op;}//cout<<cnt<<endl;tmp=read();it=st.lower_bound(seg(tmp,tmp));//cout<<(*it).l<<" "<<(*it).r<<"\n";//cout<<state[(*it).l]<<"\n";cout<<query(root[(*it).l],1,n,tmp-(*it).l+1,state[(*it).l])<<"\n";}
另外我总感觉这数据有点弱。
转载于:https://www.cnblogs.com/intwentieth/p/10421230.html
BZOJ4552: [Tjoi2016Heoi2016]排序相关推荐
- bzoj千题计划128:bzoj4552: [Tjoi2016Heoi2016]排序
http://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案 把>=mid 的数看做1,<mid 的数看做0 这样升序.降序排列相当于 ...
- [BZOJ] 4552: [Tjoi2016Heoi2016]排序
通过各种手段把序列问题变成01序列问题可以简化问题 这里可以用二分答案,把大于等于的变成1,小于的变成0 然后区间排序就是线段树区间赋值操作啦 复杂度\(O(nlog^2n)\) #include&l ...
- bzoj 4552: [Tjoi2016Heoi2016]排序
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个 ...
- [Tjoi2016Heoi2016]排序[01序列]
4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec Memory Limit: 256 MB Submit: 994 Solved: 546 [S ...
- 【TJOI2016】【bzoj4552】排序(二分答案+线段树01排序)
problem 给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序 排序分为两种 1:(0,l,r)表示将区间[l,r]的数字升序排序 2:(1,l,r)表示将区间[l,r]的数字降序排序 ...
- 线段树 by yyb
线段树 by yyb Type1 维护特殊信息 1.[洛谷1438]无聊的数列 维护一个数列,两种操作 1.给一段区间加上一个等差数列 2.单点询问值 维护等差数列 不难发现,等差数列可以写成\(ad ...
- 【BZOJ4552】【TJOI2016HEOI2016】排序(线段树、二分)
Description 在2016年,佳媛姐姐喜欢上了数字序列. 因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的: 给出一个1到n的全排列,现在 ...
- 数据库中自定义排序规则,Mysql中自定义字段排序规则,Oracle中自定义字段排序规则,decode函数的用法,field函数的用法
数据库中自定义排序 场景:有一张banner表,表中有一个status字段,有0, 1, 2三个状态位,我想要 1,0,2的自定义排序(这里是重点),然后再进行之上对sequence字段进行二次排序( ...
- 伍六七带你学算法 进阶篇-排序算法
给定一个整数数组 nums,将该数组升序排列. 示例 1: 输入:[5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:[5,1,1,2,0,0] 输出:[0,0,1,1,2,5] 各排序算 ...
最新文章
- Linux内核中的platform机制
- Java-Runoob-高级教程-实例-数组:01. Java 实例 – 数组排序及元素查找
- 产品规划,要考虑哪些方面?
- 针对各组项目的改进意见
- java web购物车代码_java web开发之购物车功能实现示例代码
- 源码与tarball套件管理程序笔记摘录
- [html] html标签的属性值是否可以省略引号?为什么?
- npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! node-sass@
- MMP,我说每年年会我怎么老是中不了奖,原来是这样
- @Controller与@RestController有何区别
- 【js高三】---js模块模式
- 任正非:HR面试不深刻导致大规模进人、走人,耽误人家几年对得起人家吗?...
- 实操:SparrowRecsys的首次运行
- 学Java看这就完事了!javasocket编程例子
- 【2023王道数据结构】【树与二叉树】通过C++实现中序遍历的非递归算法(手动入出栈)C、C++完整实现(可直接运行
- ANSA二次开发实战——车身弯扭刚度计算文件自动生成(1)
- 利用python读取tomcat中log文件提取出错误日志生成新的文件
- 一行代码深度定制你的专属二维码:(amzqr、MyQR制作动态二维码)
- tensorflow官方Blog-使用Keras Tuner超参数优化框架 进行超参数调整 ,具体实现版本
- Tomcat重启单个服务
热门文章
- python中凯撒密码_python实现凯撒密码、凯撒加解密算法
- python字符串格式化 说明符顺序_python实践分享:格式化字符串时使用.format方式还是“%”...
- 数据预处理之数据描述
- Leetcode 208:实现Trie(前缀树)
- 社区发现(一)--算法综述
- 微服务实现不同登陆_PaaS与IaaS在微服务架构实现方面的6大不同
- python爬取b站403_使用Python爬取B站全站视频信息
- cpu爆了怎么排查和处理_CPU飙高,系统性能问题如何排查?
- docker容器启动与停止命令
- presto求时间差