zoukankan      html  css  js  c++  java
  • 【BZOJ】2209: [Jsoi2011]括号序列(splay)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2209

    splay又犯逗。。。。。。。。upd1那里的sum忘记赋值反。。。。。。。。。。。。。

    本题好神。。首先发现将所有能匹配的消掉后一定是类似这样的))))((((,当然也有((((((这种情况

    还有本题将查询的区间长度都看做偶数。。。。。

    如果能知道有多少个)和多少个(,那么答案就是

    )的个数除以2取上界+(的个数除以2取上界

    很简单吧。。。。。。

    所以我们只需要在splay维护从左边剩余的)最多有多少个,右边(最多有多少个即可。

    但是由于操作2和操作3的存在,我们还需要维护左边剩余的(最多有多少个,右边)最多有多少个,这样就能支持了。。

    然后请自己yy

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int oo=~0u>>1, N=1e5+10;
    struct node *null;
    struct node {
    	node *f, *c[2];
    	int s, k, lmin, lmax, rmin, rmax, sum;
    	bool tag, rev;
    	node(int _k=0) { s=1; lmin=lmax=rmin=rmax=k=sum=_k; f=c[0]=c[1]=null; tag=rev=0; }
    	void setc(node *x, bool d) { c[d]=x; x->f=this; }
    	bool d() { return f->c[1]==this; }
    	void pushup() {
    		s=c[0]->s+c[1]->s+1;
    		sum=c[0]->sum+c[1]->sum+k;
    		lmin=c[0]->lmin;
    		lmax=c[0]->lmax;
    		rmin=c[1]->rmin;
    		rmax=c[1]->rmax;
    		int mnl=min(0, c[1]->lmin), mnr=min(0, c[0]->rmin);
    		int mxl=max(0, c[1]->lmax), mxr=max(0, c[0]->rmax);
    		lmin=min(lmin, c[0]->sum+k+mnl);
    		lmax=max(lmax, c[0]->sum+k+mxl);
    		rmin=min(rmin, c[1]->sum+k+mnr);
    		rmax=max(rmax, c[1]->sum+k+mxr);
    	}
    	void upd1() {
    		if(this==null) return;
    		tag=!tag;
    		int t=lmin;
    		lmin=-lmax;
    		lmax=-t;
    		t=rmin;
    		rmin=-rmax;
    		rmax=-t;
    		k=-k;
    		sum=-sum;
    	}
    	void upd2() {
    		if(this==null) return;
    		rev=!rev;
    		swap(c[0], c[1]);
    		swap(lmin, rmin);
    		swap(lmax, rmax);
    	}
    	void pushdown() {
    		if(tag) {
    			tag=0;
    			c[0]->upd1();
    			c[1]->upd1();
    		}
    		if(rev) {
    			rev=0;
    			c[0]->upd2();
    			c[1]->upd2();
    		}
    	}
    }*root;
    void PN(node *x) {
    	printf("key:%c 	 lmin:%d 	 lmax:%d 	 rmin:%d 	 rmax:%d 	 sum:%d 	 
    ", x->k==1?'(':(x->k==-1?')':'N'), x->lmin, x->lmax, x->rmin, x->rmax, x->sum);
    }
    void Pr(node *x) {
    	if(x==null) return;
    	Pr(x->c[0]);
    	if(x->k) printf("%c", x->k==1?'(':')');
    	Pr(x->c[1]);
    }
    void P(node *x=root) {
    	Pr(x); puts("");
    }
    void rot(node *x) {
    	node *f=x->f;
    	f->pushdown(); x->pushdown(); bool d=x->d();
    	f->f->setc(x, f->d());
    	f->setc(x->c[!d], d);
    	x->setc(f, !d);
    	f->pushup();
    	if(f==root) root=x;
    }
    void splay(node *x, node *f=null) {
    	x->pushdown();
    	while(x->f!=f)
    		if(x->f->f==f) rot(x);
    		else x->d()==x->f->d()?(rot(x->f), rot(x)):(rot(x), rot(x));
    	x->pushup();
    }
    node *sel(node *x, int k) {
    	if(x==null) return x;
    	x->pushdown();
    	int s=x->c[0]->s;
    	if(s==k) return x;
    	if(s<k) return sel(x->c[1], k-s-1);
    	return sel(x->c[0], k);
    }
    node *getrange(int l, int r) {
    	splay(sel(root, l-1));
    	splay(sel(root, r+1), root);
    	return root->c[1]->c[0];
    }
    void fix1() {
    	int l=getint(), r=getint();
    	node *x=getrange(l, r);
    	x->pushdown();
    	x->upd1();
    }
    void fix2() {
    	int l=getint(), r=getint();
    	node *x=getrange(l, r);
    	x->pushdown();
    	x->upd2();
    }
    void ask() {
    	int l=getint(), r=getint();
    	node *x=getrange(l, r);
    	l=(-x->lmin+1)>>1;
    	r=(x->rmax+1)>>1;
    	printf("%d
    ", l+r);
    }
    
    char s[N];
    int n, m, q;
    void build(int l, int r, node *&x) {
    	if(l>r) return;
    	int mid=(l+r)>>1;
    	x=new node(s[mid]==')'?-1:1);
    	if(l==r) return;
    	build(l, mid-1, x->c[0]);
    	build(mid+1, r, x->c[1]);
    	if(l<=mid-1) x->c[0]->f=x;
    	if(mid+1<=r) x->c[1]->f=x;
    	x->pushup();
    }
    void in(node *x) {
    	x->lmax=x->rmax=-oo;
    	x->lmin=x->rmin=oo;
    	x->sum=0;
    	x->k=0;
    }
    void init() {
    	null=new node(); null->s=0; in(null);
    	null->f=null->c[0]=null->c[1]=null;
    	root=new node(); in(root);
    	root->setc(new node(), 1); in(root->c[1]);
    	node *x;
    	read(n); read(m);
    	scanf("%s", s+1);
    	build(1, n, x);
    	root->c[1]->setc(x, 0);
    	root->c[1]->pushup();
    	root->pushup();
    }
    
    int main() {
    	init();
    	while(m--) {
    		int c=getint();
    		if(c==0) ask();
    		else if(c==1) fix1();
    		else if(c==2) fix2();
    	}
    	return 0;
    }
    

      


    Description

    Input

    输入数据的第一行包含两个整数N和Q,分别表示括号序列的长度,以及操作的个数。 第二行包含一个长度为N的括号序列。 接下来Q行,每行三个整数t、x和y,分别表示操作的类型、操作的开始位置和操作的结 束位置,输入数据保证x不小于y。其中t=0表示询问操作、t=1表示反转操作、t=2表示翻转操 作。

    Output

    对于每一个询问操作,输出一行,表示将括号序列的该子序列修改为配对,所需的最少改动 个数。

    Sample Input

    6 3
    )(())(
    0 1 6
    0 1 4
    0 3 4

    Sample Output

    2
    2
    0

    HINT

    100%的数据满足N,Q不超过10^5

    Source

  • 相关阅读:
    智慧养老民政监管平台建设方案
    CF600E Lomsat gelral dsu on tree
    dsu on tree详解
    【Spring 从0开始】Spring5 新功能,整合日志框架 Log4j2
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 数据库事务参数
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 操作数据库
    【Spring 从0开始】AOP 操作
    【Spring 从0开始】AOP 操作中的相关术语、环境准备
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4149149.html
Copyright © 2011-2022 走看看