CF1149C 题解

易知每个点到根节点的距离 \(dep_u\)\(u\) 前左括号的个数减 \(u\) 前右括号的个数。

两个点 \(u\)\(v\) 之间的距离为 \(dep_u+dep_v-2*dep_{lca(u,v)}\),而 \(lca(u,v)\) 就是括号序列中 \(u\)\(v\) 之间 \(dep\) 最小的点。

所以只要维护所有 \((u,w,v)\) 中最大的 \(dep_u+dep_v-2*dep_w\) 就行了,可以用线段树实现,写起来有点麻烦。

#include <iostream>
#include <cstring>
#include <cstdio>
#define Hibiki namespace
#define Wataru std
using Hibiki Wataru;

int n,q,a[200002],dep[200002];
char s[200002];

struct node{
	int mx,mi,lef,rgt,sum,tag;
};

struct Segment_tree{
	node ma[1000002];
	void Pushup(int num) {
		ma[num].mx=max(ma[num*2].mx,ma[num*2+1].mx);
		ma[num].mi=min(ma[num*2].mi,ma[num*2+1].mi);
		
		ma[num].lef=max(ma[num*2].lef,ma[num*2+1].lef);
		ma[num].lef=max(ma[num].lef,ma[num*2].mx-2*ma[num*2+1].mi);
		ma[num].rgt=max(ma[num*2].rgt,ma[num*2+1].rgt);
		ma[num].rgt=max(ma[num].rgt,ma[num*2+1].mx-2*ma[num*2].mi);
		
		ma[num].sum=max(ma[num*2].sum,ma[num*2+1].sum);
		ma[num].sum=max(ma[num].sum,ma[num*2].lef+ma[num*2+1].mx);
		ma[num].sum=max(ma[num].sum,ma[num*2].mx+ma[num*2+1].rgt);
	}
	void Solve(int num,int x) {
		ma[num].mx+=x,ma[num].mi+=x;
		ma[num].lef-=x,ma[num].rgt-=x;
		ma[num].tag+=x;
	}
	void Pushdown(int num) {
		if(ma[num].tag) {
			Solve(num*2,ma[num].tag);
			Solve(num*2+1,ma[num].tag);
			ma[num].tag=0;
		}
	}
	void Build(int num,int l,int r) {
		if(l==r) {
			ma[num].mx=ma[num].mi=dep[l];
			ma[num].lef=ma[num].rgt=-dep[l];
			return ;
		}
		int mid=(l+r)/2;
		Build(num*2,l,mid);
		Build(num*2+1,mid+1,r);
		Pushup(num);
	}
	void Update(int num,int l,int r,int ll,int rr,int x) {
		if(l>rr || r<ll) return ;
		if(ll<=l && rr>=r) {
			Solve(num,x);
			return ;
		}
		Pushdown(num);
		int mid=(l+r)/2;
		Update(num*2,l,mid,ll,rr,x);
		Update(num*2+1,mid+1,r,ll,rr,x);
		Pushup(num);
	}
	int Query() {
		return ma[1].sum;
	}
}Tree;

int main() {
	scanf("%d%d",&n,&q);
	cin>>s+1;
	for(int i=1;i<=2*n-2;i++) 
		if(s[i]=='(') a[i]=1,dep[i]=dep[i-1]+1;
		else a[i]=-1,dep[i]=dep[i-1]-1;
	Tree.Build(1,1,2*n-2);
	printf("%d\n",Tree.Query());
	while(q--) {
		int l,r;
		scanf("%d%d",&l,&r);
		if(l!=r) {
			Tree.Update(1,1,2*n-2,l,2*n-2,a[r]-a[l]);
			Tree.Update(1,1,2*n-2,r,2*n-2,a[l]-a[r]);
			swap(a[l],a[r]);
		}
		printf("%d\n",Tree.Query());
	}
	return 0;
}
posted @ 2022-08-02 08:11  Sharing666  阅读(57)  评论(1)    收藏  举报