// Jakub Rozek
// Nawiasy
// PA 2022 B r5
// czas: n^2*log(n) + k*n*log(n)
// pami: n^2
#include "bits/stdc++.h"
using namespace std;
const int N=4003;
const int INFi=1000000009;
const long long INF=1000000000000000018;
long long n,k,R=1;
string s;
long long tree[N*4];
long long nawt[N][N];
long long dp[2][N];
int minwar(int w, int a, int b, int c, int d)
{
if(a>d || b<c) return INFi;
if(c<=a && b<=d) return tree[w];
return min(minwar(w*2,a,(a+b)/2,c,d),minwar(w*2+1,(a+b)/2+1,b,c,d));
}
long long naw(int a, int b)
{
return nawt[a][b];
}
void licz(int l, int a, int b, int p, int k)
{
if(a>b) return;
int c=(a+b)/2, sr=p, nawiasy;
dp[l][c]=INF;
for(int j=p; j<min(c,k); ++j)
{
nawiasy=naw(j+1,c);
if(dp[1-l][j]+nawiasy<dp[l][c])
{
dp[l][c]=dp[1-l][j]+nawiasy;
sr=j;
}
}
licz(l,a,c-1,p,sr+1);
licz(l,c+1,b,sr,k);
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
long long a,b,c;
cin>>n>>k>>s;
while(R<n) R*=2;
a=0;
for(int i=0; i<n; ++i)
{
if(s[i]=='(') ++a;
else --a;
tree[R+i+1]=a;
}
for(int i=R-1; i>0; --i) tree[i]=min(tree[i*2],tree[i*2+1]);
for(int d=1; d<n; ++d)
{
a=0;b=a+d;
while(b<n)
{
nawt[a][b]=nawt[a+1][b]+nawt[a][b-1]-nawt[a+1][b-1];
if(tree[R+a]==tree[R+b+1])
{
c=minwar(1,0,R-1, a,b);
if(c>=tree[R+a]) nawt[a][b]++;
}
++a;
++b;
}
}
for(int i=0; i<n; ++i) dp[1][i]=naw(0,i);
for(int l=2; l<=k; ++l) licz(l%2,0,n-1,0,n);
cout<<dp[k%2][n-1]<<"\n";
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | // Jakub Rozek // Nawiasy // PA 2022 B r5 // czas: n^2*log(n) + k*n*log(n) // pami: n^2 #include "bits/stdc++.h" using namespace std; const int N=4003; const int INFi=1000000009; const long long INF=1000000000000000018; long long n,k,R=1; string s; long long tree[N*4]; long long nawt[N][N]; long long dp[2][N]; int minwar(int w, int a, int b, int c, int d) { if(a>d || b<c) return INFi; if(c<=a && b<=d) return tree[w]; return min(minwar(w*2,a,(a+b)/2,c,d),minwar(w*2+1,(a+b)/2+1,b,c,d)); } long long naw(int a, int b) { return nawt[a][b]; } void licz(int l, int a, int b, int p, int k) { if(a>b) return; int c=(a+b)/2, sr=p, nawiasy; dp[l][c]=INF; for(int j=p; j<min(c,k); ++j) { nawiasy=naw(j+1,c); if(dp[1-l][j]+nawiasy<dp[l][c]) { dp[l][c]=dp[1-l][j]+nawiasy; sr=j; } } licz(l,a,c-1,p,sr+1); licz(l,c+1,b,sr,k); } int main() { ios_base::sync_with_stdio(0); cin.tie(0); long long a,b,c; cin>>n>>k>>s; while(R<n) R*=2; a=0; for(int i=0; i<n; ++i) { if(s[i]=='(') ++a; else --a; tree[R+i+1]=a; } for(int i=R-1; i>0; --i) tree[i]=min(tree[i*2],tree[i*2+1]); for(int d=1; d<n; ++d) { a=0;b=a+d; while(b<n) { nawt[a][b]=nawt[a+1][b]+nawt[a][b-1]-nawt[a+1][b-1]; if(tree[R+a]==tree[R+b+1]) { c=minwar(1,0,R-1, a,b); if(c>=tree[R+a]) nawt[a][b]++; } ++a; ++b; } } for(int i=0; i<n; ++i) dp[1][i]=naw(0,i); for(int l=2; l<=k; ++l) licz(l%2,0,n-1,0,n); cout<<dp[k%2][n-1]<<"\n"; return 0; } |
English