思路求证伪/hack
查看原帖
思路求证伪/hack
499682
operator_楼主2023/10/5 17:21

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;
}

2023/10/5 17:21
加载中...