zoukankan      html  css  js  c++  java
  • BZOJ2329: [HNOI2011]括号修复

    用1表示左括号,-1表示右括号,lmin表示从左开始的最小连续和,rmax表示从右开始的最大连续和,答案为(1-lmin)/2+(1+rmax)/2,splay维护即可。

    #include<algorithm>
    #include<cstdio>
    #define Z(o)(o->i->s1+1)
    #define M (i+j>>1)
    using namespace std;
    const int N=1e5+5;
    typedef struct node*ptr;
    struct node{
    	ptr i,j;
    	int v,t1,t2,t3,s1,s2,s3,s4,s5,s6;
    	ptr up(){
    		i->down(),j->down();
    		s1=i->s1+1+j->s1;
    		s2=i->s2+v+j->s2;
    		s3=min(i->s3,i->s2+v+j->s3);
    		s4=max(i->s4,i->s2+v+j->s4);
    		s5=min(j->s5,j->s2+v+i->s5);
    		s6=max(j->s6,j->s2+v+i->s6);
    		return this;
    	}
    	ptr down();
    }e[N];
    ptr node::down(){
    	if(this==e)return e;
    	if(t1){
    		i->t1=j->t1=v=t1,s2=s1*t1;
    		if(t1>0)
    			s3=s5=0,s4=s6=s2;
    		else
    			s4=s6=0,s3=s5=s2;
    		t1=t2=t3=0;
    	}
    	if(t2&&t2--){
    		i->t2^=1,j->t2^=1;
    		swap(i,j);
    		swap(s3,s5);
    		swap(s4,s6);
    	}
    	if(t3&&t3--){
    		i->t3^=1,i->t1*=-1;
    		j->t3^=1,j->t1*=-1;
    		v*=-1,s2*=-1;
    		swap(s3*=-1,s4*=-1);
    		swap(s5*=-1,s6*=-1);
    	}
    	return this;
    }
    ptr a=e;
    ptr pre(char*z,int i,int j){
    	if(i>j)return e;
    	node s={pre(z,i,M-1),pre(z,M+1,j),z[M]=='('?1:-1};
    	return(*++a=s).up();
    }
    void zig(ptr&o,ptr&s){ptr t=o->i;o->i=s,s=o->up(),o=t;}
    void zag(ptr&o,ptr&s){ptr t=o->j;o->j=s,s=o->up(),o=t;}
    ptr splay(int v,ptr&o){
    	ptr s=e,t=e;
    	while(v!=Z(o->down()))
    		if(v<Z(o)){
    			if(v<Z(o->i->down()))
    				zig(o,o->i->j);
    			zig(o,s);
    		}else{
    			v-=Z(o);
    			if(v>Z(o->j->down()))
    				v-=Z(o->j),zag(o,o->j->i);
    			zag(o,t);
    		}
    	while(s!=e)zig(s,o->j);
    	while(t!=e)zag(t,o->i);
    	return o->up();
    }
    ptr&splay(int s,int t,ptr&r){
    	splay(s,r);
    	return splay(t-s+2,r->j)->i;
    }
    int main(){
    	int n,m,s,t;
    	static char c,f[N],z[N];
    	scanf("%d%d%s",&n,&m,f+1);
    	ptr r=pre(f,0,n+1);
    	while(m--){
    		scanf("%s%d%d",z,&s,&t);
    		ptr o=splay(s,t,r);
    		if(*z=='R')
    			scanf(" %c",&c),o->t1=c=='('?1:-1;
    		if(*z=='S')o->t2=1;
    		if(*z=='I')o->t3=1;
    		if(*z=='Q')
    			printf("%d
    ",(1-o->s3)/2+(1+o->s6)/2);
    	}
    }
    
  • 相关阅读:
    自己实现的一个简单的C# IOC 容器
    C# 内存缓存工具类 MemoryCacheUtil
    使用触发器和C#程序实现数据同步
    Maven 命令安装指定 jar 包到本地仓库
    C# RSA 非对称加密
    JS可选链操作符?.和双问号??
    Learn D3 入门文档: Introduction
    Lerna 基本概念
    图片 src 为二进制的处理
    ASCII 和 Base64
  • 原文地址:https://www.cnblogs.com/f321dd/p/5496015.html
Copyright © 2011-2022 走看看