社区讨论

求问此做法的复杂度

P14567【MX-S12-T2】区间参与者 3已保存回复 6

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@mi9zax8i
此快照首次捕获于
2025/11/22 15:39
3 个月前
此快照最后确认于
2025/11/22 16:40
3 个月前
查看原帖
rt。
呜呜呜,蒟蒻考场想出来的神奇思路,A了。
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std ; 

const int N = 1e6 + 10 ; 
/*
    @details:
    input -> color 
    cost -> val 
    f -> force 
*/
int input[ N ] , cost[ N ] ; 
int f[ N ] , to[ N ] ; 
int n , tot = 0 ; 
struct segment
{
    int left ; 
    int right ; 
    int cost ; 
    segment( ) { cost = 0 ; }
    segment( int l , int r ) : left( l ) , right( r ) { }  
    bool operator < ( const segment &a ) 
    {
        return ( right == a.right ? left > a.left : right < a.right ) ; 
    }
} solve[ N ] ; 

class segment_tree 
{
    public:
    struct node 
    {
        int data ; 
        int left ; 
        int right ; 
    } seg[ N << 2 ] ; 
    void build( int u , int l , int r ) 
    {
        seg[ u ].left = l , seg[ u ].right = r ; 
        if( l == r ) 
        {
            seg[ u ].data = to[ l ] ; 
            return ; 
        }
        int mid = l + r >> 1 ; 
        build( u << 1 , l , mid ) ;
        build( u << 1 | 1 , mid + 1 , r ) ; 
        seg[ u ].data = max( seg[ u << 1 ].data , seg[ u << 1 | 1 ].data ) ;  
    }
    int ask( int u , int l , int r ) 
    {
        if( seg[ u ].left >= l && seg[ u ].right <= r ) 
        {
            return seg[ u ].data ; 
        }
        int mid = seg[ u ].left + seg[ u ].right >> 1 ; 
        int sum = 0 ; 
        if( l <= mid ) sum = max( sum , ask( u << 1 , l , r ) ) ; 
        if( r > mid ) sum = max( sum , ask( u << 1 | 1 , l , r ) ) ; 
        return sum ; 
    }
} s ;

class segment_tree1
{
public:
    struct node
    {
        bool data;
        bool add ; 
        int left;
        int right;
    } seg[N << 2];
    void push_down( int u ) 
    {
        if( seg[ u ].add == 0 ) return ; 
        seg[ u << 1 ].data |= seg[ u ].add ; 
        seg[ u << 1 | 1 ].data |= seg[ u ].add ;
        seg[ u << 1 ].add |= seg[ u ].add ; 
        seg[ u << 1 | 1 ].add |= seg[ u ].add ; 
        seg[ u ].add = 0 ; 
    }

    void build(int u, int l, int r)
    {
        seg[u].left = l, seg[u].right = r;
        seg[ u ].add = 0 ; 
        if (l == r)
        {
            seg[u].data = 0 ;
            return;
        }
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        seg[u].data = seg[u << 1].data | seg[u << 1 | 1].data;
    }
    bool ask(int u, int l, int r)
    {
        if (seg[u].left >= l && seg[u].right <= r)
        {
            return seg[u].data;
        }
        int mid = seg[u].left + seg[u].right >> 1;
        push_down( u ) ; 
        bool sum = 0;
        if (l <= mid)
            sum = sum | ask(u << 1, l, r) ;
        if (r > mid)
            sum = sum | ask(u << 1 | 1, l, r) ;
        return sum;
    }
    void insert( int u , int l , int r ) 
    {
        if( seg[ u ].left >= l && seg[ u ].right <= r ) 
        {
            seg[ u ].data = 1 ; 
            seg[ u ].add = 1 ; 
            return ; 
        }
        int mid = seg[ u ].left + seg[ u ].right >> 1 ;
        push_down( u ) ;  
        if( l <= mid ) insert( u << 1 , l , r  ) ; 
        if( r > mid ) insert( u << 1 | 1 , l , r ) ; 
        seg[ u ].data = seg[ u << 1 ].data | seg[ u << 1 | 1 ].data ; 
    }
} s1 ;

int mape[ N ] , belong[ N ] , lo[ N ] ; 

signed main()
{
    // freopen( "interval.in" , "r" , stdin ) ; 
    // freopen( "interval.out" , "w" , stdout ) ;
    ios::sync_with_stdio( false ) ; 
    cin.tie( 0 ) , cout.tie( 0 ) ;  
    cin >> n ; 
    for( int i = 1 ; i <= n ; i ++ ) cin >> input[ i ] ; 
    for( int i = 1 ; i <= n ; i ++ ) cin >> cost[ i ] ; 
    for( int i = 1 ; i <= n ; i ++ ) cin >> f[ i ] ; 
    for( int i = n ; i >= 1 ; i -- ) 
    {
        to[ i ] = mape[ input[ i ] ] ; 
        mape[ input[ i ] ] = i ; 
    }
    s.build( 1 , 1 , n ) ; 
    s1.build( 1 , 1 , n ) ; 
    for( int l = 1 ; l <= n ; l ++ )
    {
        int r = l , flage = 1 ; 
        while( 1 ) 
        {
            int u = s.ask( 1 , l , r ) ; 
            if( s1.ask( 1 , l , r ) == 1 ) 
            {
                flage = 0 ; 
                break ; 
            } 
            if( u <= r ) break ; 
            r = u ; 
        } 
        if( flage ) 
            solve[ ++ tot ] = segment( l , r ) ; 
        s1.insert( 1 , to[ l ] , to[ l ] ) ; 
    }
    s1.build( 1 , 1 , n ) ; 
    sort( solve + 1 , solve + 1 + tot ) ; 
    int final_ans = LLONG_MAX ; 
    for( int i = 1 ; i <= tot ; i ++ ) 
    {
        int ans = 0 ; 
        if( s1.ask( 1 , solve[ i ].left , solve[ i ].right ) ) continue ; 
        s1.insert( 1 , solve[ i ].left , solve[ i ].right ) ; 
        for( int j = solve[ i ].left ; j <= solve[ i ].right ; j ++ ) 
            ans += ( cost[ j ] * ( f[ j - solve[ i ].left + 1 ] ) ) ; 
        final_ans = min( ans , final_ans ) ; 
    }
    cout << final_ans << "\n" ; 

    return 0 ; 
}

回复

6 条回复,欢迎继续交流。

正在加载回复...