zoukankan      html  css  js  c++  java
  • 区间伸缩算法小礼包

    区间伸缩算法小礼包

    主要还是用来优化结合其他算法时的复杂度,ssw02就用两道题浅谈一下总结吧

    欢迎转载ssw02的博客:https://www.cnblogs.com/ssw02/p/11674544.html


    逛画展

    题面
    博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,

    a和b,代表他要看展览中的第 a 幅至第 b 幅画(包含 a 和 b)之间的所有图画,而门票

    的价钱就是一张图画一元。

    为了看到更多名师的画,wangjy希望入场后可以看到所有名师的图画(至少各一张)。

    可是他又想节省金钱。。。

    作为wangjy的朋友,他请你写一个程序决定他购买门票时的 a 值和 b 值。

    思路

    这道题比较水,我们考虑存在任何一个恰好的合法区间 [L,R] 时,当 L 向右移动时,R 不可能向左移动,所以 L,R 在最小合法时的移动方向一定一样。

    然后直接上代码了

    代码

    #include<bits/stdc++.h>
    using namespace std ;
    const int MAXN = 1000005 ;
    inline int read(){
    	int s=0 ; char g=getchar() ;while( g>'9'||g<'0' )g=getchar() ;
    	while( g>='0'&&g<='9' )s=s*10+g-'0',g=getchar() ; return s;
    }
    int  N , M , cnt[ 2005 ] , a[ MAXN ] ;
    int  q[ MAXN ] , l , r , tot , ansl , ansr , ans ;
    int main(){
    	N = read() , M = read() , ans = (1<<30) ;
    	for( int i = 1 ; i <= N ; ++i )a[i] = read() ;
    	for( l = 1 , r = 0 ; l <= N ; ){
    		while( tot < M && r < N ){
    			if( cnt[ a[++r] ] == 0 )tot++ ;
    			cnt[ a[r] ]++ ;
    		}
    		while( l <= N ){
    			if( cnt[ a[l] ] == 1 )break ;
    			else
    				cnt[ a[l++] ]-- ;
    		}
    		if( tot != M )break ;
    		if( r-l+1 < ans )//记录较小的 
    			ans = r-l+1 , ansl = l , ansr = r ;
    		if( cnt[ a[l] ]==1 )tot--;
    		cnt[a[l]]--,l++ ;
    	}
    	cout<<ansl<<" "<<ansr ;
    	return 0 ;
    }
    

    [SCOI2009]生日礼物

    先放上面那道题是为了减轻这道题的思维难度(不过本来这道题也没什么思维难度)

    区别:1.范围特别大,当有效的点最多还是 1e6 个 , 考虑读入后离散化 ,对于每个点上存储的颜色使用vector存一下即可。

    然后就是把上面的单个修改改为离散化后的单点多个修改即可。还是使用类似单调队列的区间推移操作即可。

    #include<bits/stdc++.h>
    using namespace std ;
    inline int read(){
    	int s=0 ; char g=getchar() ; while( g>'9'||g<'0' )g=getchar() ;
    	while( g>='0'&&g<='9' )s=s*10+g-'0',g=getchar() ; return s ;
    }
    int N , K , tot , cnt[ 61 ] , p[ 1000005 ] , id[ 1000005 ] ;
    vector<int>num[ 1000005 ] ;
    struct ap{
    	int  loc , col ,  id ;
    }t[ 1000005 ] ; 
    inline bool cmp( ap x , ap y ){
    	return (x.loc==y.loc)?(x.col<y.col):(x.loc < y.loc) ;
    }
    int main(){
    	N = read() , K = read() ; int m1 , m2=0 ;
    	for( int i = 1 ; i <= K ; ++i ){
    		m1 = read() ;
    		for( int j = 1 ; j <= m1 ; ++j )t[++m2].loc=read(),t[m2].col=i ;
    	} 
    	sort( t+1 , t+N+1 , cmp ) ;
    	int now = 0 , loc = 0 , ans = 2147483647 ;
    	for( int i = 1 ; i <= N ; ++i ){
    		if( now != t[i].loc )now=t[i].loc,loc++,id[loc] = now ; 
    		num[loc].push_back(t[i].col) ; 
    	} 
    	for( int l = 1 , r = 0 ; l <= loc ; ){
    		while( tot < K && r < loc ){
    			int number = num[ ++r ].size() ;
    		    for( int j = 0 ; j < number ; ++j ){
    		    	if( cnt[ num[r][j] ] == 0 )tot++ ;
    		    	cnt[ num[r][j] ]++ ;
    		    } 
    		}
    		while( l <= loc ){
    			bool flag = true ; int number = num[l].size() ;
    			for( int j = 0 ; j < number ; ++j )
    				if( cnt[ num[l][j] ] == 1 ){flag=false;break;}
    			if( flag ){
    				for( int j = 0 ; j < number ; ++j )
    			        cnt[ num[l][j] ]-- ;
    			    ++l ;
    			}
    			else break ;
    		}
    		if( tot != K )break ;
    		if( id[r]-id[l] < ans )
    			ans = id[r]-id[l] ;
    		int number = num[l].size() ;
    		for( int j = 0 ; j < number ; ++j ){
    			if( cnt[ num[l][j] ] == 1 )tot-- ;
    			cnt[ num[l][j] ]-- ; 
    		}
    		l++ ;
    	}
    	cout<<ans ;
    	return 0 ;
    }
    

    欢迎转载ssw02的博客:https://www.cnblogs.com/ssw02/p/11674544.html

  • 相关阅读:
    (引)spring学习笔记1.什么是控制反转
    Arduino 各种模块篇 步进电机 step motor 舵机 servo 直流电机 总复习
    Raspberry Pi Wireless Adaptor
    Pyramid 使用总结1
    Arduino 各种模块篇 人体红外感应模块 proximity sensor
    Pyramid 使用总结2
    Webcam Streaming Desktop Recording on Linux for ubuntu or its destros
    Arduino 各种模块篇 步进电机 step motor( 不用库,不用shield, 纯)
    Arduino 各种模块篇 motor shield 电机扩展板(舵机、直流电机、步进电机party)
    转载 stepper motors
  • 原文地址:https://www.cnblogs.com/ssw02/p/11674544.html
Copyright © 2011-2022 走看看