CF1750E
先来考虑一个子串怎么算最小贡献,设其有
首先,存在一个构造,操作次数为
- 依次考虑每一个左括号,如果有未匹配的右括号,则这些右括号在此左括号前面。可以直接把左括号转到某一个右括号前面。否则在该左括号右边加一个右括号。
并且,我们发现每次操作只会减少至多一个未匹配的左括号或者右括号,因此上述构造取到最优。
现在,我们来分别求出
对于
对于
时间复杂度为
代码中标记了哪个式子是在算哪一部分。
#include<bits/stdc++.h>
#define int long long
const int N=1000005;
using namespace std;
void solve(){
int n;cin>>n;
string s;cin>>s;
vector<int> a(1);
int sum=0;
for(int i=0;i<n;i++){
if(s[i]=='(')sum++;
else sum--;
a.push_back(sum);
}
sort(a.begin(),a.end());
int res=0,ns=0;
for(int i=0;i<=n;i++){
res+=i*a[i]-ns;//|L-R|
res+=i*(n-i+1);// L+R
ns+=a[i];
}
res/=2;
stack<int> sss;
for(int i=0;i<n;i++){
if(s[i]=='('){
sss.push(i);
}else{
if(sss.empty())continue;
res-=(sss.top()+1)*(n-i);// X
sss.pop();
}
}
cout<<res<<endl;
}
main(){
ios::sync_with_stdio(0);
int _T=1;cin>>_T;
while(_T--)solve();
}