BZOJ 3339: Rmq Problem 穿了棉袄的线段树
来源:互联网 发布:什么叫做网络 编辑:程序博客网 时间:2024/04/25 13:28
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1332 Solved: 709
Description
Input
Output
Sample Input
7 5
0 2 1 0 1 3 2
1 3
2 3
1 4
3 6
2 7
Sample Output
3
0
3
2
4
HINT
Source
By Xhr
题解:
这道题的线段树显然不是裸的
我们就是求一个区间mex嘛,于是我们可以把所有询问离线一下,按照左端点排序,然后每次维护的是对于这个左端点的一直到n的线段树,每个点都表示这个点到当前的这个左端点的mex值,计算方法其实很简单,我们记录一个nxt数组,nxt数组表示和这个点的值相同的值的下一个位置,如果这个值为0的话就赋为n+1,现在如果我们要从l转移到l+1,那么我们就看这个l,如果这个点可以影响到后面的话,也就是说,如果比后面的某个点的mex值小的话,那么删除了之后,显然这个点的mex值就应该变成l的值,因为l的值被删了,而mex表示的是第一个没有出现的值如果本来后面的就小的话就不影响,所以我们就可以讨论一下大小关系,然后取min值,我是抄的黄学长的代码,感觉线段树写的好不清真啊,主要是因为头有点昏,所以直接敲了一遍a了,希望复习吧
第一遍可以O(n)求mex,因为我们发现最开始从1到x的mex值都是递增的,因此可以利用这个递增性,O(n)地去求最开始的mex值,nxt值也可以O(n)求,只需要倒着for就可以了,真的是好巧妙啊,这题总之处处都很巧妙,很有意思
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int INF = 0x7fffffff;int n,m,k=0;const int MAXN = 200005;int a[MAXN],sg[MAXN],ans[MAXN],nxt[MAXN],last[MAXN];struct Tree{ int mex; } tree[ MAXN * 4 ];bool mark[200001];struct Q{ int l, r, id; } q[200005];bool cmp(Q a,Q b) { return a.l < b.l; }void pushdown( int l, int r, int rt ) { if( l == r ) return; tree[ rt << 1 ].mex = min( tree[rt].mex, tree[ rt << 1 ].mex ); tree[ rt << 1 | 1 ].mex = min( tree[rt].mex, tree[ rt << 1 | 1 ].mex );}int query( int R, int l, int r, int rt ) { if( tree[rt].mex != INF ) pushdown( l, r, rt ); if( l == r ) return tree[rt].mex; int mid = ( l + r ) >> 1; if( R <= mid ) return query( R, l, mid, rt << 1 ); else return query( R, mid + 1, r, rt << 1 | 1 );}void modify( int L, int R, int val, int l, int r, int rt ) { if( tree[rt].mex != INF ) pushdown( l, r, rt ); if( L == l && R == r ) { tree[rt].mex = min( tree[rt].mex, val ); return ; } int mid = ( l + r ) >> 1; if( R <= mid ) modify( L, R, val, l, mid, rt << 1 ); else if( L > mid ) modify( L, R, val, mid + 1, r, rt << 1 | 1 ); else { modify( L, mid, val, l, mid, rt << 1 ); modify( mid + 1, R, val, mid + 1, r, rt << 1 | 1 ); }}void build( int l, int r, int rt ) { tree[rt].mex = INF; if( l == r ) { tree[rt].mex = sg[l]; return; } int mid = ( l + r ) >> 1; build( l, mid, rt << 1 ); build( mid + 1, r, rt << 1 | 1 );}int main( ) { scanf( "%d%d", &n, &m ); for( register int i = 1; i <= n; i++ ) scanf( "%d", &a[i] ); for( register int i = 1; i <= n; i++ ) { mark[a[i]] = 1; if( a[i] == k ) while( mark[k] ) k++; sg[i] = k; } build( 1, n, 1 ); for( register int i = n; i > 0; i-- ) nxt[i] = last[a[i]], last[a[i]] = i; for( register int i = 1; i <= m; i++ ) { scanf( "%d%d", &q[i].l, &q[i].r ); q[i].id = i; } sort( q + 1, q + m + 1, cmp ); int now = 1; for( register int i = 1; i <= m; i++ ) { while( now < q[i].l ) { if( !nxt[now] ) nxt[now] = n + 1; modify( now, nxt[now] - 1, a[now], 1, n, 1 ); now++; } ans[q[i].id] = query( q[i].r, 1, n, 1 ); } for( register int i = 1; i <= m; i++ ) printf( "%d\n", ans[i] ); return 0;}
阅读全文
0 1
- BZOJ 3339: Rmq Problem 穿了棉袄的线段树
- bzoj 3339: Rmq Problem(线段树)
- bzoj 3339 Rmq problem 离线+线段树
- BZOJ 3339 Rmq Problem【离线,值域线段树
- BZOJ 3339 Rmq Problem
- bzoj 3339: Rmq Problem
- 【bzoj 3339】: Rmq Problem
- bzoj 3339: Rmq Problem
- BZOJ 3339: Rmq Problem
- BZOJ 3339: Rmq Problem
- BZOJ 3339: Rmq Problem 莫队水题
- BZOJ3339: Rmq Problem 线段树
- bzoj 3489: A simple rmq problem 可持久化线段树套可持久化线段树
- hdu-5443-The Water Problem -裸的RMQ线段树
- BZOJ 3339: Rmq Problem|莫队算法
- BZOJ 3585/3339 mex/Rmq Problem 莫队
- 【BZOJ3339】Rmq Problem【离线】【线段树】【mex】
- [BZOJ3339]Rmq Problem(离线+线段树)
- matlab permute函数
- Ubuntu下LAMP环境搭建 Apache、MySQL、PHP
- [cnblogs镜像]AFNetworking 提示"The resource could not be loaded because the App Transport Security
- Tomcat 可以运行但localhost:8080打不开
- Delphi东京版FireDAC连接MSSQL2000
- BZOJ 3339: Rmq Problem 穿了棉袄的线段树
- [cnblogs镜像]protocol 和delegate(协议和代理)的区别
- 信息系统项目管理师考试系列--(1)考试基本信息
- Java: ArrayList、LinkedList、Vector
- JQuery常用函数
- 代码哪里有问题,和的结果怎么显示不对?应该是220,怎么是6768669
- Shadowsocks限制设备连接数 和 限制端口速度 的方法
- Web客户端的几种存储方式
- [cnblogs镜像] 只声明对象也能调用方法但不起作用的原因分析