[机房测试]10.25

[机房测试]10.25

T2爆0啦,只有123啦

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


考试的时间点记录

14:32 T1结束 开T2

14:35 验证T1

14:53 T2无思路,开T3

15:12 开T3暴力

16:11 T3 50分

16:46 T2 50分有锅

16:54 T2 改完

board

点双联通分量嘛,由于题目特殊,打个特判+记录度数也可以过

change

神仙。。。。

逻辑推理+分类讨论
结论是:如果a=1,10,100,1000并且b != 2a,那么答案是2,否则是1.
考虑为什么,⾸先分析1,2,5,10这⼏个⼩的,如果a = 1,b >= 5,那么⼀定需要⾄少2,否则只需要1(这个⾃⼰可
以枚举⽅案证明)。
然后考虑⼤的的情况,举个例⼦,如果a = 10,b = 50,那么买了1之后,需要找零49,这个9肯定是⽤1,2,5凑出来
的(这⾥的意思是,能拼出49,⼀定能拼出9,然后剩下的部分即使有1,2,5,他们也⼀定能拼出10),减掉他们之
后相当于⽤10,20,去凑40,就回到了上⾯的情况。其他情况类似证明。

#include<bits/stdc++.h>
using namespace std ;
const int MAXN = 100005 ;
const int val[14]={0,1,2,5,10,20,50,100,200,500,1000,2000,5000,10000}; 
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 T , A , B ; 
int main(){
    freopen("change.in","r",stdin);
    freopen("change.out","w",stdout);
    T = read() ;
    while( T-- ){
        A = read() , B = read() ; 
        int flag = 2 ;
        if( B == 1 || B == 100 || B == 10 || B == 1000 )flag-- ;
        if( A != B*2 )flag-- ;
        if( flag )cout<<1<<endl ;
        else cout<<2<<endl ;    
    }
    return 0 ;
}

fill

话说。。。为什么50分比满分还要难写啊!!!!!!!!!

10分 ,枚举+树上暴跳
+40分 , 转化为序列贪心右端点排序。

话说,ssw02都想到了贪心,为啥没想到贪lca呢?

按照询问的lca从深到浅贪心即可。

如果左右点在dfn上没有被覆盖,那么把lca的子树全部打标记。

用个数据结构维护下区间加即可。

50

#include<bits/stdc++.h>
using namespace std ;
const int MAXN = 100005 ; 
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 T , N , M , ans , fa[MAXN] , dep[MAXN] , d[MAXN] , rev[MAXN] , cnt ;
int head[MAXN] , to[MAXN*2] , nex[MAXN*2] , tot = 1 ;
bool vis[MAXN] ; 
struct ap{
    int  a, b  ;
}t[MAXN];
inline bool cmp( ap x , ap y ){
    return ( x.b == y.b )?(x.a<y.a):(x.b<y.b) ;
}
void  add( int x , int y ){
    to[ ++tot ] = y , nex[tot] = head[x] , head[x] = tot ; 
}
bool lis( int x , int y ){
    if( vis[x] || vis[y] )return true ;
    if( x==y && vis[x]==0 )return false ; 
    while( x!=y ){
        if( dep[x] < dep[y] )swap( x,y ) ;
         if( vis[ fa[x] ] )return true ;
         x=fa[x] ;
    }
    return false ;
}
int check(){
    int flag = (1<<30) ; 
    for( int i=1 ; i<=M ; ++i ){
        if( !lis( t[i].a , t[i].b ) )return flag ;
    }
    flag=0 ;
    for( int i=1 ; i<=N ; ++i )if( vis[i] )flag++ ;
    return flag ;
}
void  find( int stp ){
    if( stp > N )return ;
    vis[stp] = true ; ans = min( check() , ans ) ; 
    find( stp+1 ) ;
    vis[stp] = false ; ans = min( check() , ans ) ; 
    find( stp+1 ) ;
}
void  dfs( int u , int father ){
    fa[u] = father ;
    for( int i = head[u] ; i ; i = nex[i] ){
        if( to[i] == father )continue ;
        dep[ to[i] ] = dep[u] + 1 ;
        dfs( to[i] , u ) ;  
    }
}
void  dfs2( int u , int father ){
    fa[u] = father ; rev[u] = ++cnt ; 
    for( int i = head[u] ; i ; i = nex[i] ){
        if( to[i] == father )continue ;
        dfs2( to[i] , u ) ;
    }
}
void  work1(){
    int m1 , m2 ; ans = (1<<30) ; 
    for( int i = 1 ;  i < N ; ++i ){
        m1 = read() , m2 = read() ;
        add( m1 , m2 ) , add( m2 , m1 ) ; 
    } 
    dfs( 1 , 1 ) ;
    for( int i = 1 ; i <= M ; ++i )t[i].a = read() , t[i].b = read() ;
    find( 1 ) ; 
    cout<<min( ans , N )<<endl ;
}
void  work2(){
    int m1 , m2 ; ans = (1<<30) ;
    for( int i = 1 ; i < N ; ++i ){
        m1 = read() , m2 = read() ; d[m1]++ , d[m2]++ ;
        add( m1 , m2 ) , add( m2 , m1 ) ;
    }
    for( int i = 1 ; i <= N ; ++i )
        if( d[i] == 1 ){dfs2( d[i] , d[i] ) ; break ; }//扫出新的序列 
    for( int i = 1 ; i <= M ; ++i ){
        m1 = read() , m2 = read() ;
        if( rev[m1] > rev[m2] )swap( m1 , m2 ) ;
        t[i].a=rev[m1] , t[i].b = rev[m2] ;
    }
    sort( t+1 , t+M+1 , cmp ) ; 
    ans = 1 ; int now = t[1].b ;
    for( register int i = 2 ; i <= M ; ++i ){
        if( t[i].a <= now )continue ;
        now = t[i].b , ans++ ;
    }
    cout<<min(ans,N)<<endl ;
}
void  clear(){
    for( register int i = 1 ; i <= N ; ++i )
    rev[i] = d[i] = t[i].a = t[i].b = head[i] = dep[i] = fa[i] = vis[i] = 0 ;
    tot = 1 , ans = (1<<30) , cnt = 0 ;
}
int main(){
    freopen("fill.in","r",stdin) ;
    freopen("fill.out","w",stdout) ;
    T = read() ;
    while( T-- ){
        N = read() , M = read() ;
        if( M==0 ){puts("0");continue;} 
        if( N <= 12 && M <= 30 )work1() ;
        else work2() ; 
        clear() ;
    }
    return 0 ;
}

ac

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
const int MAXN = 100005 ; 
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 T , N , M , tot = 1 , cnt ;
int  head[MAXN] , to[MAXN*2] , nex[MAXN*2] , dep[MAXN] , dfn[MAXN] , rev[MAXN] , anc[MAXN][20] , out[MAXN] ;
int  c[MAXN] ;
struct ap{
    int l , r , tp ; 
}t[MAXN];
//-------------
void  updata( int x , int y ){
    for( ; x <= N ; x += x&-x )c[x] += y ; 
}
ll sum( int x ){
    ll anss = 0 ;
    for( ; x ; x-= x&-x )anss += (ll)c[x] ;
    return anss ; 
}
//-------------
inline bool cmp( ap x , ap y ){
    return ( dep[ rev[x.tp] ] == dep[ rev[y.tp] ] )?( x.tp > y.tp ):(dep[ rev[x.tp] ]>dep[ rev[y.tp] ]) ;
    //return dep[ rev[x.tp] ]>dep[ rev[y.tp] ] ;
}
void add( int x , int y ){
    to[ ++tot ] = y , nex[tot] = head[x] , head[x] = tot ;
}
int lca( int x , int y ){
    if( dep[x] < dep[y] )swap( x , y ) ; 
    int t = dep[x] - dep[y] ;
    for( int p=0 ; t ; t >>=1 , ++p )
        if( t&1 )x = anc[x][p] ;
    if( x==y )return x ;
    for( int p=17 ; anc[x][0] != anc[y][0] ; p-- )
        if( anc[x][p] != anc[y][p] )x=anc[x][p] , y=anc[y][p] ;
    return anc[x][0] ;  
}
void  dfs( int u , int fa ){
    anc[u][0] = fa , dfn[u] = ++cnt , rev[cnt] = u ; 
    for( int i = 1 ; i <= 17 ; ++i )anc[u][i] = anc[ anc[u][i-1] ][i-1] ;
    for( int i = head[u] ; i ; i = nex[i] ){
        if( to[i] == fa )continue ;
        dep[ to[i] ] = dep[u] + 1 ;
        dfs( to[i] , u ) ;
    }
    out[u] = cnt ;
}
void  work(){
    int m1 , m2 ; 
    for( int i = 1 ; i < N ; ++i ){
        m1 = read() , m2 = read() ; 
        add( m1 , m2 ) , add( m2 , m1 ) ;
    }
    dfs( 1 , 1 ) ; 
    for( int i = 1 ; i <= M ; ++i ){
        m1 = read() , m2 = read() ;
        int tp = lca( m1 , m2 ) ;  
        if( dfn[m1] > dfn[m2] )swap( m1 , m2 ) ; 
        t[i].l = dfn[m1] , t[i].r = dfn[m2] , t[i].tp = dfn[tp] ; 
    }   
    sort( t+1 , t+M+1 , cmp ) ; int ans = 0 ;
    for( int i = 1 ; i <= M ; ++i ){
        //if( sum( t[i].tp )  )continue ;
        if( sum( t[i].l ) || sum( t[i].r ) )continue ;
        updata( t[i].tp , 1 ) , updata( out[ rev[ t[i].tp ] ]+1 , -1 ) ;ans++ ;
    }
    cout<<ans<<endl ;
} 
void  clear(){
    for( register int i = 1 ; i <= max( N , M ) ; ++i )out[i] = t[i].tp = t[i].l = t[i].r = c[i] = head[i] = dep[i] = dfn[i] = rev[i] = 0 ;
    tot = 1 , cnt = 0 ;
}
int main(){
    freopen("fill.in","r",stdin) ;
    freopen("fill.out","w",stdout) ;
    T = read() ;
    while( T-- ){
        N = read() , M = read() ; 
        work() ; 
        clear() ; 
    }
    return 0 ;
}
上一篇:LintCode37-反转一个3位整数


下一篇:leetcode刷题记录之7