#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,int>P;
const int N=100005;
const ll inf=1LL<<60;
int n,m,i,x,y,s[N],q[N],t,left[N],right[N],lc[N],rc[N];char a[N];
int st,en,cnt[N<<1],last[N<<1];
ll sum,ans,two,L,R,MID,pre[N],suf[N];
P f[N];
inline void go(int l,int r){
int i;
while(st>l){
st--;
sum+=right[st]>=en?cnt[s[st]]:rc[st];
cnt[s[st]]++;
}
while(en<r){
en++;
sum+=left[en]<=st?cnt[s[en]]:lc[en];
cnt[s[en]]++;
}
while(st<l){
cnt[s[st]]--;
sum-=right[st]>=en?cnt[s[st]]:rc[st];
st++;
}
while(en>r){
cnt[s[en]]--;
sum-=left[en]<=st?cnt[s[en]]:lc[en];
en--;
}
}
void solve(int l,int r,int dl,int dr){
int mid=(l+r)>>1,dm;P best(inf,0);
for(int i=dl;i<=dr;i++){
go(i,mid);
P now=f[i];
now.first+=sum;
if(now<best)best=now,dm=i;
}
best.first+=MID;
best.second++;
f[mid]=min(f[mid],best);
if(l<mid)solve(l,mid-1,dl,dm);
if(r>mid)solve(mid+1,r,dm,dr);
}
void cdq(int l,int r){
if(l==r){
//printf("dp[%d]=%lld %d\n",l,f[l].first,f[l].second);
return;
}
int mid=(l+r)>>1;
cdq(l,mid);
sum=0;
for(int i=l-1;i<=r;i++)cnt[s[i]]=0;
cnt[s[st=en=l-1]]=1;
solve(mid+1,r,l,mid);
cdq(mid+1,r);
}
int main(){
scanf("%d%d%s",&n,&m,a+1);
s[0]=n;
for(i=1;i<=n;i++)if(a[i]=='(')s[i]=s[i-1]+1;else s[i]=s[i-1]-1;
/*s[l-1]==s[r] left[r]<=l-1 || right[l-1]>=r*/
for(q[t=0]=i=0;i<=n;q[++t]=i++){
while(t&&s[q[t]]>=s[i])t--;
left[i]=q[t];
}
for(q[t=0]=i=n;~i;q[++t]=i--){
while(t&&s[q[t]]>=s[i])t--;
right[i]=q[t];
}
for(i=0;i<=n+n;i++)last[i]=-1;
for(i=0;i<=n;i++){
x=s[i];
y=last[x];
if(y>=left[i])lc[i]=lc[y]+1;
last[x]=i;
pre[i]=lc[i];
if(i)pre[i]+=pre[i-1];
}
for(i=0;i<=n+n;i++)last[i]=n+1;
for(i=n;~i;i--){
x=s[i];
y=last[x];
if(y<=right[i])rc[i]=rc[y]+1;
last[x]=i;
suf[i]=rc[i];
if(i<n)suf[i]+=suf[i+1];
}
ans=pre[n];
if(m==1)return printf("%lld",ans),0;
two=ans;
for(i=1;i<n;i++)two=min(two,pre[i]+suf[i]);
if(m==2)return printf("%lld",two),0;
L=0,R=ans-two;
while(L<=R){
MID=(L+R)>>1;
for(i=1;i<=n;i++)f[i]=P(inf,0);
cdq(0,n);
//printf("MID=%lld first=%lld second=%d\n",MID,f[n].first,f[n].second);
if(f[n].second<=m){
ans=f[n].first-MID*m;
R=MID-1;
}else{
L=MID+1;
}
}
printf("%lld",ans);
}
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; typedef pair<ll,int>P; const int N=100005; const ll inf=1LL<<60; int n,m,i,x,y,s[N],q[N],t,left[N],right[N],lc[N],rc[N];char a[N]; int st,en,cnt[N<<1],last[N<<1]; ll sum,ans,two,L,R,MID,pre[N],suf[N]; P f[N]; inline void go(int l,int r){ int i; while(st>l){ st--; sum+=right[st]>=en?cnt[s[st]]:rc[st]; cnt[s[st]]++; } while(en<r){ en++; sum+=left[en]<=st?cnt[s[en]]:lc[en]; cnt[s[en]]++; } while(st<l){ cnt[s[st]]--; sum-=right[st]>=en?cnt[s[st]]:rc[st]; st++; } while(en>r){ cnt[s[en]]--; sum-=left[en]<=st?cnt[s[en]]:lc[en]; en--; } } void solve(int l,int r,int dl,int dr){ int mid=(l+r)>>1,dm;P best(inf,0); for(int i=dl;i<=dr;i++){ go(i,mid); P now=f[i]; now.first+=sum; if(now<best)best=now,dm=i; } best.first+=MID; best.second++; f[mid]=min(f[mid],best); if(l<mid)solve(l,mid-1,dl,dm); if(r>mid)solve(mid+1,r,dm,dr); } void cdq(int l,int r){ if(l==r){ //printf("dp[%d]=%lld %d\n",l,f[l].first,f[l].second); return; } int mid=(l+r)>>1; cdq(l,mid); sum=0; for(int i=l-1;i<=r;i++)cnt[s[i]]=0; cnt[s[st=en=l-1]]=1; solve(mid+1,r,l,mid); cdq(mid+1,r); } int main(){ scanf("%d%d%s",&n,&m,a+1); s[0]=n; for(i=1;i<=n;i++)if(a[i]=='(')s[i]=s[i-1]+1;else s[i]=s[i-1]-1; /*s[l-1]==s[r] left[r]<=l-1 || right[l-1]>=r*/ for(q[t=0]=i=0;i<=n;q[++t]=i++){ while(t&&s[q[t]]>=s[i])t--; left[i]=q[t]; } for(q[t=0]=i=n;~i;q[++t]=i--){ while(t&&s[q[t]]>=s[i])t--; right[i]=q[t]; } for(i=0;i<=n+n;i++)last[i]=-1; for(i=0;i<=n;i++){ x=s[i]; y=last[x]; if(y>=left[i])lc[i]=lc[y]+1; last[x]=i; pre[i]=lc[i]; if(i)pre[i]+=pre[i-1]; } for(i=0;i<=n+n;i++)last[i]=n+1; for(i=n;~i;i--){ x=s[i]; y=last[x]; if(y<=right[i])rc[i]=rc[y]+1; last[x]=i; suf[i]=rc[i]; if(i<n)suf[i]+=suf[i+1]; } ans=pre[n]; if(m==1)return printf("%lld",ans),0; two=ans; for(i=1;i<n;i++)two=min(two,pre[i]+suf[i]); if(m==2)return printf("%lld",two),0; L=0,R=ans-two; while(L<=R){ MID=(L+R)>>1; for(i=1;i<=n;i++)f[i]=P(inf,0); cdq(0,n); //printf("MID=%lld first=%lld second=%d\n",MID,f[n].first,f[n].second); if(f[n].second<=m){ ans=f[n].first-MID*m; R=MID-1; }else{ L=MID+1; } } printf("%lld",ans); } |
English