转化之后的题意:
给出一个环,每个位置都是一种颜色的左括号或右括号
寻找一个环的切割位置,满足从这个位置切割之后得到的链中,单独看每一种颜色的括号能够匹配的颜色种类数最大
输出最小的切割位置和最大匹配的种类数
单独看一种颜色的括号
左括号+1,右括号-1
如果一个位置切割之后满足条件,那么
要求这种颜色所有的加1减1之和为0
而且是是前缀和最小的位置
这个位置直到下一个同颜色的位置之间都可以作为切割点
把所颜色的这些区间找出来即可
复杂度分析
最多一个左括号产生一个区间
所以有O(n)个区间
#include<cstdio> #include<vector> #include<algorithm> using namespace std; #define N 1000005 #define lowbit(x) x&-x struct node { int val,pos; }tmp; vector<node>v[N]; int n,c[N]; int tot[N]; int main() { int x; char cc; scanf("%d",&n); int m=0; for(int i=1;i<=n;++i) { cc=getchar(); cc=getchar(); scanf("%d",&x); m=max(m,x); tmp.pos=i; if(cc=='s') { tmp.val=1; tot[x]++; } else { tmp.val=-1; tot[x]--; } v[x].push_back(tmp); } int len; int mi,l,r,now; for(int i=1;i<=m;++i) { len=v[i].size(); if(!len || tot[i]) continue; now=0; mi=0; for(int j=0;j<len;++j) { now+=v[i][j].val; if(now<mi) mi=now; } now=0; if(now==mi) { c[1]++; c[v[i][0].pos+1]--; } for(int j=0;j<len;++j) { now+=v[i][j].val; if(now==mi) { c[v[i][j].pos+1]++; if(j!=len-1) c[v[i][j+1].pos+1]--; } } } int mx=-1,ans=0; for(int i=1;i<=n;++i) { now+=c[i]; if(now>mx) { mx=now; ans=i; } } printf("%d %d",ans,mx); }