社区讨论
求问此做法的复杂度
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 条回复,欢迎继续交流。
正在加载回复...