【ZJOI2013】K 大数查询 ( 树状数组套线段树 )
来源:互联网 发布:淘宝上金牌卖家可信吗 编辑:程序博客网 时间:2024/06/05 15:47
Description
有n 个位置和m 个操作。操作有两种,每次操作如果是1 a b c 的形式,表示往第a 个位置到第b 个位置每个位置加入一个数c。如果操作形如2 a b c 的形式,表示询问从第a 个位置到第b 个位置,第c 大的数是多少。
Input
在输入文件sequence.in 中,第一行两个数n,m。意义如题目描述。
接下来m 行每行形如1 a b c 或者2 a b c 如题目描述。
Output
在输出文件sequence.out 中,对于每个询问回答k 大数是多少。
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
Data Constraint
30%的数据n=m=1000
100%的数据n,m≤50000,并且后7 个点的数据n,m 的范围从32000 到50000近似成等差数列递增。a≤b≤n,1 操作中|c|≤n,2 操作中|c|≤maxlongint
嗯 , 应该要自然地想到二分答案 , 然后呢?
判定性问题 , 我想知道对于二分出的x,在区间l,r中有多少大于x的数的个数。
那应该想到开一个权值树状数组,里面套个线段树记录位置。
线段树要动态开节点, 为了方便, 我们不采取下传标记方式,比较麻烦。
对于线段树每个节点,(像昨天做的线段数套单调队列一样 )开两个变量,
cover 与pass
对于插入,遇到区间完整覆盖的,cover ++ , 对于路过的节点pass都加上其目标节点的区间大小( _r - _l + 1 )。
对于查询,遇到区间完整覆盖的,直接返回其pass值,其余非完整覆盖的,返回cover * ( _r - _l + 1 ) + Ask_Value_of_SubNode
这种线段树的打法避免了平常打法的复杂的标记。
#include<cstdio>#include<algorithm>#include<cstring>using namespace std ;#define N 50010#define lowbit( x ) x & -xint i , j , k , n , m , T ;struct SegmentTree { int l , r ; int cover , pass ;}tr[13183043] ;int rot[N] ;struct data { int typ , c , a , b ;}a[N] ;struct rec { int ps , va ;}d[N] ;bool cmp( rec a , rec b ) { return a.va < b.va ;}int disva = 0 ;int demap[N] ;void SegIns( int l , int r, int _l , int _r , int po ) { int m = l + r >> 1 ; tr[po].pass += _r - _l + 1 ; if( _l==l && _r==r ) { tr[po].cover += 1 ; return ; } if( _r<=m ) SegIns( l , m , _l , _r , ( tr[po].l==0 ? tr[po].l = ++ T : tr[po].l ) ) ; else if( _l>m ) SegIns( m+1 , r , _l , _r , ( tr[po].r==0 ? tr[po].r = ++ T : tr[po].r ) ) ; else SegIns( l , m , _l , m , ( tr[po].l==0 ? tr[po].l = ++ T : tr[po].l ) ) , SegIns( m+1 , r , m+1 , _r , ( tr[po].r==0 ? tr[po].r = ++ T : tr[po].r ) ) ; }int SegAsk( int l , int r , int _l , int _r , int po ) { int m = l + r >> 1 ; if( po==0 ) return 0 ; if( _l==l && _r==r ) return tr[po].pass ; if( _r<=m ) return SegAsk( l , m , _l , _r , tr[po].l ) + tr[po].cover * ( _r - _l + 1 ) ; else if( _l>m ) return SegAsk( m+1 , r , _l , _r , tr[po].r ) + tr[po].cover * ( _r - _l + 1 ) ; else return SegAsk( l , m , _l , m , tr[po].l ) + SegAsk( m+1 , r , m+1 , _r , tr[po].r ) + tr[po].cover * ( _r - _l + 1 ) ;}void Insert( int x , int l , int r ) { for( ; x>0 ; x-=lowbit( x ) ) { if( rot[x]==0 ) rot[x] = ++ T ; SegIns( 1 , n , l , r , rot[x] ) ; }}bool Ask( int x , int l , int r , int va ) { int ret = 0 ; for( ; x<=disva ; x+=lowbit( x ) ) { ret += SegAsk( 1 , n , l , r , rot[x] ) ; } return ret >= va ;}int tot = 0 ;int main() { scanf("%d%d",&n,&m ) ; for( i=1 ; i<=m ; i++ ) { scanf("%d%d%d%d",&a[i].typ , &a[i].a , &a[i].b , &a[i].c ) ; if( a[i].typ==1 ) d[++tot].ps = i , d[tot].va = a[i].c ; } sort( d+1 , d+1+tot , cmp ) ; d[0].va = -0x7fffffff ; for( i=1 ; i<=tot ; i++ ) { if( d[i].va != d[i-1].va ) ++disva , demap[ disva ] = d[i].va ; a[ d[i].ps ].c = disva ; } for( i=1 ; i<=m ; i++ ) { if( a[i].typ==1 ) { // insert Insert( a[i].c , a[i].a , a[i].b ) ; } else { int L = 1 , R = disva ; while( L<=R ) { int M = L+R >> 1 ; if( Ask( M , a[i].a , a[i].b , a[i].c ) ) L = M + 1 ; else R = M - 1 ; } printf("%d\n",demap[R] ) ; } }}
Debuglog
把询问的c也离散化了。。。。。傻逼的可以
- 【ZJOI2013】K 大数查询 ( 树状数组套线段树 )
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
- BSOJ3723:ZJOI2013 k大数查询 线段树套线段树
- bzoj3110[Zjoi2013]K大数查询 主席树套线段树
- [BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
- [BZOJ3110][Zjoi2013]K大数查询(主席树套线段树||整体二分 )
- 【BZOJ3110】【Zjoi2013】K大数查询 树套树 权值线段树套区间线段树
- BZOJ 3110: [Zjoi2013]K大数查询|线段树套线段树
- 3110: [Zjoi2013]K大数查询 线段树套线段树 标记永久化
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
- 【bzoj3110】【ZJOI2013】【K大数查询】【权值线段树套位置线段树】
- bzoj 3110: [Zjoi2013]K大数查询 线段树套线段树
- BZOJ 3110 [Zjoi2013]K大数查询 (整体二分 + 树状数组或线段树处理区间合值)
- HDU 5412 CRB and Queries && BZOJ 3110: [Zjoi2013]K大数查询 (整体二分+树状数组/线段树)
- 【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
- BZOJ 3110 [Zjoi2013]K大数查询(整体二分+树状数组)
- BZOJ_P3110 [ZJOI2013]K大数查询(线段树+整体二分)
- [BZOJ]3110: [Zjoi2013]K大数查询 整体二分+线段树
- css基础精华04
- hive与hbase集成
- Heartbeat概念详解
- android 添加视频、图片、录音上传(一)
- css基础精华05
- 【ZJOI2013】K 大数查询 ( 树状数组套线段树 )
- Centos7下Amarok播放mp3
- NYOJ 27 水池数目 (DFS)
- 程序员的生活充满压力,但你不能放弃!
- 推箱子
- poj 3590
- C++,当函数参数或者返回值是对象......(★firecat推荐★)
- 黑马程序员——正则与反射
- OJ刷题---奇怪的分式