二分

P5502 [JSOI2015] 最大公约数

二分真恶心人。

对于这类题目,显然可以枚举左端点,向右快速跳合法的右端点。

发现 \(gcd\) 一旦减小就一定至少除以 \(2\) ,那么显然对于一个左端点,二分右端点只会二分 \(logV\) 次,那么总体复杂度就是 \(lognlogV\)

再加上 \(gcd\) 的复杂度 \(logV\),那么时间复杂度为 \(O(n\log n \log ^2V)\)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+(r-l)/2)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 1e5 + 5;

int read()
{
    int f = 1 , x = 0;
    char ch = getchar();
    while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
    while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
    return x * f;
}

int n , a[N] , ans , lg[N];

struct ST
{
    int st[N][26];
    void init()
    {
        for ( int i = 1 ; i <= n ; i ++ ) st[i][0] = a[i];
        for ( int j = 1 ; j <= __lg(n) ; j ++ )
            for ( int i = 1 ; i + ( 1 << j ) - 1 <= n ; i ++ ) 
                st[i][j] = __gcd ( st[i][j-1] , st[i+(1<<j-1)][j-1] );
    }
    int query ( int l , int r )  
    {
        int len = __lg(r-l+1);
        return __gcd ( st[l][len] , st[r-(1<<len)+1][len] );
    }
}st;

int que ( int x , int y )
{
    int tmp = st.query ( x , y );
    int l = x , r = n;
    while ( l <= r )
    {
        if ( st.query ( x , mid ) < tmp ) r = mid - 1;
        else l = mid + 1;
    } 
    return r;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    int T = read();
    while ( T -- )
    {
        ans = 0;
        n = read();
        for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
        st.init();
        for ( int l = 1 ; l <= n ; l ++ )
        {
            int r = l;
            while ( r <= n )
            {
                int tmpr = que ( l , r );
                ans = max ( ans , st.query ( l , r ) * ( tmpr - l + 1 ) );
                r = tmpr + 1;
            }
        }
        cout << ans << endl;
    }
	return 0;
}

P1020 [NOIP1999 普及组] 导弹拦截

第一问是求最长不升子序列,第二问是求最长上升子序列。

\(O(n^2)\):

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 1e5 + 5;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , f[N] , ans , a[N] , g[N];

signed main ()
{
 	ios::sync_with_stdio(false);
 	cin.tie(0) , cout.tie(0);
    while ( cin >> a[++n] ); -- n;
    for ( int i = 1 ; i <= n ; i ++ ) f[i] = g[i] = 1;
    for ( int i = 1 ; i <= n ; i ++ )
        for ( int j = 1 ; j < i ; j ++ )
            if ( a[i] <= a[j] ) f[i] = max ( f[i] , f[j] + 1 );
    for ( int i = 1 ; i <= n ; i ++ ) ans = max ( ans , f[i] );
    cout << ans << endl;
    ans = 0;
    for ( int i = 1 ; i <= n ; i ++ )   
        for ( int j = 1 ; j < i ; j ++ )
            if ( a[i] > a[j] ) g[i] = max ( g[i] , g[j] + 1 );
    for ( int i = 1 ; i <= n ; i ++ ) ans = max ( ans , g[i] );
    cout << ans << endl;
	return 0;
}
posted @ 2023-11-08 19:20  Echo_Long  阅读(4)  评论(0编辑  收藏  举报