BZOJ-3526: [Poi2014]Card(线段树)

作者: acccccc | 来源:发表于2019-03-15 09:48 被阅读0次

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3526

假如不带修改,可以直接扫一遍解决,但是这个不好动态维护,我们发现分治同样可以解决这个问题,相当维护一下左边两个数到右边两个数是否可行,然后这样可以方便的线段树了,但是这样还是有点慢,考虑到左边的数固定的话,右边对应的数要越小越好,那么对于一个区间[l,r]维护一下l两个数对应的右边的数的最小值即可,如果不可行就正无穷表示,线段树上直接修改。。。没了

代码:

#include <cstdio>

#include <algorithm>

#include <cstring>

 

using namespace std ;

 

const int inf = 0x7fffffff ;

const int maxn = 201000 ;

 

int a[ maxn ][ 2 ] ;

 

struct node {

        node *lc , *rc ;

        int l , r , mid , c[ 2 ] ;

        inline void update(  ) {

                c[ 0 ] = c[ 1 ] = inf ;

                if ( lc -> c[ 0 ] <= a[ mid + 1 ][ 0 ] ) c[ 0 ] = min( c[ 0 ] , rc -> c[ 0 ] ) ;

                if ( lc -> c[ 0 ] <= a[ mid + 1 ][ 1 ] ) c[ 0 ] = min( c[ 0 ] , rc -> c[ 1 ] ) ;

                if ( lc -> c[ 1 ] <= a[ mid + 1 ][ 0 ] ) c[ 1 ] = min( c[ 1 ] , rc -> c[ 0 ] ) ;

                if ( lc -> c[ 1 ] <= a[ mid + 1 ][ 1 ] ) c[ 1 ] = min( c[ 1 ] , rc -> c[ 1 ] ) ;

        }

} sgt[ maxn << 1 ] ;

 

node *pt = sgt , *root ;

 

void build( int l , int r , node* &t ) {

        t = pt ++ ;

        t -> l = l , t -> r = r ;

        if ( l == r ) {

                t -> c[ 0 ] = a[ l ][ 0 ] , t -> c[ 1 ] = a[ l ][ 1 ] ; return ;

        }

        t -> mid = ( l + r ) >> 1 ;

        build( l , t -> mid , t -> lc ) , build( t -> mid + 1 , r , t -> rc ) ;

        t -> update(  ) ;

}

 

void change( int x , node *t ) {

        if ( t -> l == t -> r ) {

                t -> c[ 0 ] = a[ t -> l ][ 0 ] , t -> c[ 1 ] = a[ t -> l ][ 1 ] ; return ;

        }

        change( x , x <= t -> mid ? t -> lc : t -> rc ) ;

        t -> update(  ) ;

}

 

int ch ;

 

inline void getint( int &t ) {

        for ( ch = getchar(  ) ; ch < '0' || ch > '9' ; ch = getchar(  ) ) ; t = ch - '0' ;

        for ( ch = getchar(  ) ; ch >= '0' && ch <= '9' ; ch = getchar(  ) ) t = t * 10 + ch - '0' ;

}

 

int n , m ;

 

int main(  ) {

        getint( n ) ;

        for ( int i = 0 ; i ++ < n ; ) getint( a[ i ][ 0 ] ) , getint( a[ i ][ 1 ] ) ;

        build( 1 , n , root ) ;

        getint( m ) ;

        while ( m -- ) {

                int x , y ; getint( x ) , getint( y ) ;

                swap( a[ x ][ 0 ] , a[ y ][ 0 ] ) , swap( a[ x ][ 1 ] , a[ y ][ 1 ] ) ;

                change( x , root ) , change( y , root ) ;

                printf( min( root -> c[ 0 ] , root -> c[ 1 ] ) < inf ? "TAK\n" : "NIE\n" ) ;

        }

        return 0 ;

}

相关文章

  • BZOJ-3526: [Poi2014]Card(线段树)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3526 假...

  • 算法模板(七) 线段树

    线段树单点操作 线段树区间操作

  • 数据结构-线段树

    实现一个线段树 下面实现的线段树,有三个功能: 把数组构建成一颗线段树 线段树的修改 线段树的查询 303号问题 ...

  • 线段树系列之——区间更新

    第三篇线段树了——重点不在于解决题目,通过题目理解线段树才是重点 前面写了一篇关于线段树的单点更新,线段树的单点更...

  • 线段树模板

    线段树 线段树基本概念 概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组)...

  • 线段树专题整理

    待更新 线段树讲解(未读)线段树模板(未读) 模板 求区间总和 A - 敌兵布阵 HDU - 1166 题意 线段...

  • 线段树 02 构建线段树

    构建线段树 线段树的每个节点除了天然的对应一段长度外,不一定赋予其上的意义就是区间元素的和,所以两个节点向上汇聚成...

  • 线段树(区间树)

    线段树:线段树是一种二叉树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。线段树适用于不变...

  • 线段树

    专题 B线段树求逆序对 C[] D 区间不同值求和

  • 线段树

    [toc] 线段树 实现问题:常用于求数组区间最小值 时间复杂度:(1).建树复杂度:nlogn。(2).线段树算...

网友评论

    本文标题:BZOJ-3526: [Poi2014]Card(线段树)

    本文链接:https://www.haomeiwen.com/subject/rsnkmqtx.html