Submission #409996

#TimeUsernameProblemLanguageResultExecution timeMemory
409996CaroLindaThe short shank; Redemption (BOI21_prison)C++14
55 / 100
1974 ms176228 KiB
#include <bits/stdc++.h> #define sz(x) (int)(x.size()) #define all(x) x.begin(),x.end() const int MAXN = 4010 ; const int MAX = 2e6+10 ; const int MAX4 = 150004 ; using namespace std ; int N , D , T , toGet, toFill = 1 ; int t[MAX] ; int dp[2][MAX]; int cost[MAXN][MAXN] ; void solve(int l, int r, int optmin , int optmax ) { if(l > r) return ; int mid = (l+r)>>1 ; int opt = optmin ; dp[toFill][mid] = cost[opt][mid]+dp[toGet][opt-1] ; for(int i = optmin+1 ; i <= min(mid,optmax) ; i++ ) { int newCost = cost[i][mid] + dp[toGet][i-1] ; if(newCost >= dp[toFill][mid]) continue ; opt = i ; dp[toFill][mid] = newCost ; } solve(l, mid-1, optmin, opt ) ; solve(mid+1, r, opt, optmax ); } void solve2() { vector<int> dpSuf(N+2,0) ; vector<int> r(N+1,N+1) ; for(int i = N ; i > 0 ; i-- ) { r[i] = i+1 ; while( r[i] <= N && t[i]+r[i]-i < t[r[i]] ) r[i] = r[ r[i] ] ; int k = T-t[i]+i ; dpSuf[i] = dpSuf[r[i]]+max(0,min( r[i]-1 , k )-i+1 ) ; } int s = t[1]+1 ; int qtd = t[1] <= T ; int ans = qtd+dpSuf[2] ; for(int i = 2 ; i <= N ; i++ , s++ ) { s = min(s, t[i] ) ; qtd += s <= T ; ans = min(ans, qtd+dpSuf[i+1]) ; } printf("%d\n" , ans ) ; exit(0) ; } vector<int> p ; int K ; int tree[MAX4*4] ; int lz[MAX4*4] ; int m(int l, int r) { return (l+r)>>1 ; } void refresh(int pos, int l, int r) { tree[pos] += lz[pos] ; tree[pos] = min(tree[pos] , N+5) ; if(l == r) return (void)(lz[pos] = 0 ) ; lz[pos<<1] += lz[pos] ; lz[pos<<1|1] += lz[pos] ; lz[pos] = 0 ; } void clean(int pos, int l, int r, int beg, int en ) { refresh(pos,l,r) ; if(tree[pos] == N+5 || l > en || r < beg ) return ; if( l== r ) { tree[pos] = N+5 ; return ; } clean(pos<<1 , l , m(l,r) , beg, en ) ; clean(pos<<1|1 , m(l,r)+1, r , beg, en ) ; tree[pos] = min(tree[pos<<1] , tree[pos<<1|1]) ; } void getMin(int pos, int l, int r, int beg, int en, int &cur ) { refresh(pos,l,r) ; if( l > en || r < beg) return ; if( l >= beg && r <= en ) return (void)( cur = min(cur,tree[pos]) ) ; getMin(pos<<1 , l , m(l,r ) , beg, en , cur ) ; getMin(pos<<1|1 , m(l,r)+1, r, beg, en, cur ) ; } void updPoint(int pos, int l , int r, int x, int val ) { refresh(pos,l,r) ; tree[pos] = min(tree[pos] , val ) ; if( l == r ) return ; if( x <= m(l,r) ) updPoint(pos<<1 , l , m(l,r) , x , val ) ; else updPoint(pos<<1|1 , m(l,r)+1 , r, x, val ) ; } void updInterval(int pos , int l, int r, int beg, int en ) { refresh(pos,l,r) ; if(l > en || r < beg) return ; if( l >= beg && r <= en ) { lz[pos]++ ; refresh(pos,l,r) ; return ; } updInterval(pos<<1 , l , m(l,r) , beg, en ) ; updInterval(pos<<1|1 , m(l,r)+1, r, beg, en ) ; tree[pos] = min(tree[pos<<1] , tree[pos<<1|1]) ; } void solve4() { for(int i = 1 ; i <= N ; i++ ) { p.push_back( t[i]-i ) ; p.push_back( T-i ) ; } sort(all(p)) ; p.erase(unique(all(p)) , p.end() ) ; K = sz(p) ; int s = T+1 ; for(int i = 1 ; i <= N ; i++ , s++ ) { s = min(s, t[i]) ; dp[0][i] = dp[0][i-1]+(s <= T) ; } for(int j = 1 ; j <= D ; j++ , swap(toGet, toFill) ) { clean(1,0,K-1, 0, K-1 ) ; for(int i = 1 ; i <= N ; i++ ) { int a = lower_bound(all(p), t[i]-i ) - p.begin() ; int b = lower_bound(all(p), T-i ) - p.begin() ; int cur = dp[toGet][i-1] ; getMin( 1 , 0 , K-1 , a , K-1 , cur ) ; clean(1,0,K-1, a, K-1) ; updPoint(1,0,K-1, a, cur ) ; updInterval(1,0,K-1, 0, b ) ; dp[toFill][i] = N+5 ; getMin(1,0,K-1, 0, K-1 , dp[toFill][i]) ; } } printf("%d\n" , dp[toGet][N] ) ; exit(0) ; } int main() { scanf("%d %d %d", &N, &D, &T ) ; for(int i = 1 ; i <= N ; i++ ) scanf("%d", &t[i] ) ; if( D <= 1 ) solve2() ; if( D <= 15 ) solve4() ; for(int i = 1 ; i <= N ; i++ ) { int s = t[i]+1 ; cost[i][i] = t[i] <= T ; for(int j = i+1 ; j <= N ; j++ , s++ ) { s = min(s, t[j] ) ; cost[i][j] = cost[i][j-1]+(s <= T ) ; } } for(int i = 1 ; i <= N ; i++ ) dp[0][i] = cost[1][i] ; for(int i = 1 ; i <= D ; i++ , swap(toGet, toFill) ) { for(int j = 1 ; j <= i ; j++ ) dp[toFill][j] = dp[toGet][j] ; solve(i+1, N, i+1, N ) ; } printf("%d\n", dp[toGet][N] ) ; }

Compilation message (stderr)

prison.cpp: In function 'int main()':
prison.cpp:202:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  202 |  scanf("%d %d %d", &N, &D, &T  ) ;
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
prison.cpp:203:38: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  203 |  for(int i = 1 ; i <= N ; i++ ) scanf("%d", &t[i] ) ;
      |                                 ~~~~~^~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...