传送门

splay练习。

考虑把括号序列转化成类似于区间最大/最小值的情况。

显然我们可以知道括号序列消完的情况肯定是$a$个)和$b$个(,那么把这些括号全部合法化的代价显然就是$\frac{a+1}{2}+\frac{b+1}{2}$。

接着我们可以把'('变为1,把')'变为-1,然后每次取左区间的连续最小值,右区间的连续最大值,就是$a$与$b$的大小。

因为存在区间翻转,所以需要把左/右区间的连续最大/小值都搞出来。

splay即可。

//BZOJ2209
//by Cydiater
//2017.2.15
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <bitset>
#include <set>
#include <vector>
#include <complex>
using namespace std;
#define ll long long
#define up(i,j,n)	for(int i=j;i<=n;i++)
#define down(i,j,n)	for(int i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
const int MAXN=1e5+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int root,cnt=0,N,M,arr[MAXN];
char s[MAXN];
struct SplayTree{
	int son[2],l0,l1,r0,r1,sum,fa,siz,tag0,tag1,val;
}t[MAXN];
namespace solution{
	inline int get(int k){return t[t[k].fa].son[1]==k;}
	inline void reload(int k){
		int s1=t[k].son[0],s2=t[k].son[1];
		t[k].l0=min(t[s1].l0,t[s1].sum+t[k].val+t[s2].l0);
		t[k].l1=max(t[s1].l1,t[s1].sum+t[k].val+t[s2].l1);
		t[k].r0=min(t[s2].r0,t[s2].sum+t[k].val+t[s1].r0);
		t[k].r1=max(t[s2].r1,t[s2].sum+t[k].val+t[s1].r1);
		t[k].siz=t[s1].siz+t[s2].siz+1;
		t[k].sum=t[s1].sum+t[s2].sum+t[k].val;
	}
	inline void push0(int k){
		if(!k)return;
		swap(t[k].l0,t[k].l1);t[k].l0*=-1;t[k].l1*=-1;
		swap(t[k].r0,t[k].r1);t[k].r0*=-1;t[k].r1*=-1;
		t[k].tag0^=1;t[k].val*=-1;t[k].sum*=-1;
	}
	inline void push1(int k){
		if(!k)return;
		swap(t[k].l0,t[k].r0);
		swap(t[k].l1,t[k].r1);
		t[k].tag1^=1;
	}
	inline void Pushdown(int k){
		int s1=t[k].son[0],s2=t[k].son[1];
		if(t[k].tag1){
			push1(s1);push1(s2);
			swap(t[k].son[0],t[k].son[1]);
			t[k].tag1=0;
		}
		if(t[k].tag0){
			push0(s1);push0(s2);
			t[k].tag0=0;
		}
	}
	inline void rotate(int k){
		int old=t[k].fa,oldf=t[old].fa,which=get(k);
		t[old].son[which]=t[k].son[which^1];t[t[old].son[which]].fa=old;
		t[k].son[which^1]=old;t[old].fa=k;
		t[k].fa=oldf;
		if(oldf)t[oldf].son[t[oldf].son[1]==old]=k;
		reload(old);reload(k);
	}
	inline void splay(int k,int aim){
		for(int fa;(fa=t[k].fa);rotate(k)){
			if(k==aim)break;
			else if(fa==aim){
				rotate(k);
				break;
			}else if(t[fa].fa==aim){
				rotate(get(fa)==get(k)?fa:k);
				rotate(k);
				break;
			}else rotate(get(fa)==get(k)?fa:k);
		}
		if(aim==root)root=k;
	}
	int Node(int rnk){
		int now=root;
		while(true){
			Pushdown(now);
			int lsiz=t[now].son[0]?t[t[now].son[0]].siz:0;
			if(rnk<=lsiz)now=t[now].son[0];
			else{
				if(rnk==lsiz+1)return now;
				rnk-=lsiz+1;
				now=t[now].son[1];
			}
		}
	}
	int Match(int L,int R){
		int kl=Node(L),kr=Node(R+2);
		splay(kl,root);splay(kr,t[root].son[1]);
		return kr;
	}
	void Build(int L,int R,int &k,int fa){
		if(!k)k=++cnt;
		int mid=(L+R)>>1;
		t[k].fa=fa;t[k].siz=1;t[k].tag0=t[k].tag1=0;
		t[k].l0=t[k].l1=t[k].r0=t[k].r1=0;t[k].val=arr[mid];
		if(L==R){
			t[k].son[0]=t[k].son[1]=0;
			t[k].sum=t[k].val;
			t[k].l0=t[k].l1=t[k].r0=t[k].r1=t[k].val;
			cmin(t[k].l0,0);cmin(t[k].r0,0);
			cmax(t[k].l1,0);cmax(t[k].r1,0);
			return;
		}
		if(L<=mid-1)Build(L,mid-1,t[k].son[0],k);
		if(mid+1<=R)Build(mid+1,R,t[k].son[1],k);
		reload(k);
	}
	int Col(int L,int R){
		int k=Match(L,R);
		return ((t[t[k].son[0]].r1+1)/2)-((t[t[k].son[0]].l0-1)/2);
	}
	void Inv(int L,int R){
		int k=Match(L,R);
		push0(t[k].son[0]);
		reload(k);reload(t[k].fa);
	}
	void Rev(int L,int R){
		int k=Match(L,R);
		push1(t[k].son[0]);
		reload(k);reload(t[k].fa);
	}
	void Prepare(){
		N=read();M=read();
		scanf("%s",s+1);
		up(i,1,N)arr[i]=(s[i]=='('?1:-1);
		arr[0]=0;arr[N+1]=0;
		Build(0,N+1,root,0);
	}
	void Solve(){
		//DEBUG(root);
		while(M--){
			int op=read(),L=read(),R=read();
			if(op==0)printf("%d\n",Col(L,R));
			if(op==1)Inv(L,R);
			if(op==2)Rev(L,R);
		}
	}
}
int main(){
	using namespace solution;
	Prepare();
	Solve();
	return 0;
}

BZOJ2209: [Jsoi2011]括号序列的更多相关文章

  1. BZOJ2209 [Jsoi2011]括号序列 splay

    原文链接http://www.cnblogs.com/zhouzhendong/p/8093556.html 题目传送门 - BZOJ2209 题解 我太弱了,调出这题感觉都要吐了. 题解懒得写了. ...

  2. bzoj 2209: [Jsoi2011]括号序列 splay

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 833  Solved: 392[Submit][Status ...

  3. BZOJ 2209: [Jsoi2011]括号序列 [splay 括号]

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1111  Solved: 541[Submit][Statu ...

  4. bzoj 2209 [Jsoi2011]括号序列 平衡树

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1404  Solved: 699[Submit][Statu ...

  5. 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay

    [BZOJ2329/2209][HNOI2011]括号修复/[Jsoi2011]括号序列 题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作, ...

  6. 【BZOJ】2209: [Jsoi2011]括号序列(splay)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2209 splay又犯逗........upd1那里的sum忘记赋值反............. 本题 ...

  7. [HNOI2011]括号修复 / [JSOI2011]括号序列

    传送门 Solution 一道题花费了两天的时间-- 在大佬@PinkRabbit的帮助下,终于AC了,感动-- 首先,我们考虑一个括号序列被修改成合法序列需要的次数: 我们需要修改的其实是形如... ...

  8. 洛谷 P3215 [HNOI2011]括号修复 / [JSOI2011]括号序列(fhq-treap)

    题目链接 题意:有一个长度为 \(n\) 的括号序列,你需要支持以下操作: 将 \([l,r]\) 中所有括号变为 \(c\) 将 \([l,r]\) 区间翻转 将 \([l,r]\) 区间中左括号变 ...

  9. ●BZOJ 2209 [Jsoi2011]括号序列

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2209 题解: Splay 很好的题,但是把智障的我给恶心到了...   首先不难发现,最后没 ...

随机推荐

  1. 谷歌Volley网络框架讲解——HttpStack及其实现类

    前两篇已经对网络请求流程已经梳理了个大概,这次我们着重看一下HttpStack和它的其实现类.我们之前在Network篇讲过它仅有一个实现类,而今天我们讲的HttpStack有两个实现类. 其中Htt ...

  2. 微信Tinker的一切都在这里,包括源码(一)

    版权声明:本文由张绍文原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/101 来源:腾云阁 https://www.qclo ...

  3. Android 动画fillAfter和fillBefore

    fillBefore是指动画结束时画面停留在此动画的第一帧; fillAfter是指动画结束是画面停留在此动画的最后一帧. Java代码设置如下: /*****动画结束时,停留在最后一帧******* ...

  4. 配置Python实战开发环境

    一.安装Python和easy_install 和pip 新版本的linux下面应该带有这些环境,没有自带的话可以查找google配置. 二.配置python运行的虚拟化环境: 好处:Python的库 ...

  5. [算法] N 皇后

    N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行.同一列.同一斜线上的皇后都会自动攻击). 一. 求解N皇后问题是算法中回溯法应用的一个经典案例 回溯算 ...

  6. Oracle入门笔记 ——启动

    参考教材<深入浅出Oracle> 兴趣 + 勤奋 + 坚持 + 方法 ≍ 成功 DBA生存之四大守则 1.备份重于一切: 2.三思而后行: 3.rm是危险的: 4.你来制定规范: 第一章: ...

  7. CentOS中用户不在 sudoers 文件中。此事将被报告。

    首先切换为root用户 su root; 然后更改etc/sudoers文件的只读为可读可写可执行. sudo chmod 777 /etc/sudoers 输入visudo命令即可编辑文件,找到ro ...

  8. 写出gradle风格的groovy代码

    写出gradle风格的groovy代码 我们先来看一段gradle中的代码: buildscript { repositories { jcenter() } dependencies { class ...

  9. Centos设置SSH限制登录用户及IP

    1,系统版本查看 2,编辑ssh配置文件 vim /etc/ssh/sshd_config 在尾部加一行 允许sysman用户从ip1.1.1.*登录 3,重启sshd即可 /etc/init.d/s ...

  10. 朴素贝叶斯算法的python实现 -- 机器学习实战

    import numpy as np import re #词表到向量的转换函数 def loadDataSet(): postingList = [['my', 'dog', 'has', 'fle ...