rt,模拟赛题,当时我想的是求出所有可能的连续合法括号序列,按结束位置从后向前贪心,如果删去这个序列更优就删掉,其中的查询和删除一个连续序列用线段树实现。我觉得没啥问题,但是是错的,求证伪或hack。
附代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd() {
int s=0,m=0;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
}
char s[300005];
int cnt;
struct QWQ {int l,r;} a[300005];
bool cmp(QWQ a1,QWQ a2) {return a1.r>a2.r;}
int st[300005],top;
struct Node {int l,r,laz;string s;};
struct Segment_Tree {
Node t[4*300005];
int ls(int p) {return p<<1;}
int rs(int p) {return p<<1|1;}
void pushup(int p) {t[p].s=t[ls(p)].s+t[rs(p)].s;}
void pushdown(int p) {
if(!t[p].laz) return;
t[ls(p)].s="",t[rs(p)].s="";
t[ls(p)].laz=1,t[rs(p)].laz=1;
t[p].laz=0;
}
void build(int p,int l,int r) {
t[p].l=l,t[p].r=r;
if(l==r) {t[p].s=s[l];return;}
int m=(l+r)>>1;
build(ls(p),l,m);build(rs(p),m+1,r);
pushup(p);
}
void update(int p,int l,int r) {
if(l<=t[p].l&&t[p].r<=r) {
t[p].s="",t[p].laz=1;
return;
}
pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(l<=m) update(ls(p),l,r);
if(r>m) update(rs(p),l,r);
pushup(p);
}
string query(int p,int l,int r) {
if(l<=t[p].l&&t[p].r<=r) return t[p].s;
pushdown(p);
int m=(t[p].l+t[p].r)>>1;string tmp="";
if(l<=m) tmp=tmp+query(ls(p),l,r);
if(r>m) tmp=tmp+query(rs(p),l,r);
return tmp;
}
} t;
signed main() {
scanf("%s",s+1);
int n=strlen(s+1);
t.build(1,1,n);
for(int i=1;i<=n;i++) {
if(s[i]=='(')
st[++top]=i;
else {
if(top) {
a[++cnt]={st[top],i+1};
top--;
}
}
}
sort(a+1,a+cnt+1,cmp);
for(int i=1;i<=cnt;i++) {
string s1=t.query(1,a[i].l,a[i].r),s2=t.query(1,a[i].r+1,n);
if(s1!=""&&s1+s2>s2)
t.update(1,a[i].l,a[i].r);
}
cout<<t.query(1,1,n);
return 0;
}