bzoj 1095 括号序列求两点距离

大致题意: 给一棵树,每个节点最开始都是黑色,有两种操作,1.询问树中相距最远的一对黑点的距离 2.反转一个节点的颜色

一种做法:

  建立出树的括号序列,类似这样: [A[B][C]],所以长度为3*n

  假如我们要询问AC间的距离,提取出中间的括号:[]],匹配消去后得到],其长度就是距离.

  现在我们要做的就是修改点的状态,并且动态维护答案.要用到一些求与绝对值相关的式子的技巧.

  1 /**************************************************************
  2     Problem: 1095
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:2176 ms
  7     Memory:55548 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #define min(a,b) ((a)<(b)?(a):(b))
 12 #define max(a,b) ((a)>(b)?(a):(b))
 13 #define N 100010
 14 #define M N<<1
 15 #define oo 0x3f3f3f3f
 16 #define fprintf(...)
 17
 18 struct Node {
 19     int v[7], c, e, a;
 20     int lf, rg;
 21     Node *ls, *rs;
 22     void init( int type ) {
 23         if( type==0 ) {
 24             a = 0;
 25             e = false;
 26             c = 1;
 27             for( int t=0; t<7; t++ ) v[t]=0;
 28         } else if( type==-1 ) { //  (1,0)
 29             a = -1;
 30             e = true;
 31             c = 0;
 32             v[1] = v[3] = v[6] = v[2] = v[5] = 1;
 33             v[0] = v[4] = -1;
 34         } else {                //  (0,1)
 35             a = -1;
 36             e = true;
 37             c = 0;
 38             v[1] = v[3] = v[6] = v[0] = v[4] = 1;
 39             v[2] = v[5] = -1;
 40         }
 41     }
 42     void update() {
 43         e = ls->e && rs->e;
 44         v[5] = ls->v[5] + rs->v[5];
 45         v[4] = ls->v[4] + rs->v[4];
 46         v[6] = max( ls->v[6]+rs->v[4], ls->v[5]+rs->v[6] );
 47         if( !ls->e && !rs->e ) {
 48             v[0] = max( ls->v[0], ls->v[4]+rs->v[0] );
 49             v[1] = max( ls->v[1], max( ls->v[6]+rs->v[0], ls->v[5]+rs->v[1] ) );
 50             v[2] = max( rs->v[2], ls->v[2]+rs->v[5] );
 51             v[3] = max( rs->v[3], max( ls->v[3]+rs->v[4], ls->v[2]+rs->v[6] ) );
 52             a = max( max(ls->v[3]+rs->v[0],ls->v[2]+rs->v[1]), max(ls->a,rs->a) );
 53         } else if( !ls->e ) {
 54             v[0] = ls->v[0];
 55             v[1] = ls->v[1];
 56             v[2] = ls->v[2]+rs->v[5];
 57             v[3] = max( ls->v[3]+rs->v[4], ls->v[2]+rs->v[6] );
 58             a = ls->a;
 59         } else if( !rs->e ) {
 60             v[0] = ls->v[4]+rs->v[0];
 61             v[1] = max( ls->v[6]+rs->v[0], ls->v[5]+rs->v[1] );
 62             v[2] = rs->v[2];
 63             v[3] = rs->v[3];
 64             a = rs->a;
 65         } else {
 66             a = -1;
 67         }
 68     }
 69     void reverse( int pos ) {
 70         if( lf==rg ) {
 71             if( c ) {
 72                 c = 0;
 73                 a = -1;
 74                 e = true;
 75             } else {
 76                 c = 1;
 77                 a = 0;
 78                 e = false;
 79             }
 80             return;
 81         }
 82         int mid=(lf+rg)>>1;
 83         if( pos<=mid ) ls->reverse(pos);
 84         else rs->reverse(pos);
 85         update();
 86     }
 87 }pool[N*3*3], *tail=pool, *root;
 88
 89 int n, m;
 90 int head[N], dest[M], next[M], etot;
 91 int dfn[N], sgn[N*3], fat[N], idc;
 92
 93 void adde( int u, int v ) {
 94     etot++;
 95     next[etot] = head[u];
 96     dest[etot] = v;
 97     head[u] = etot;
 98 }
 99 void dfs( int u ) {
100     sgn[++idc] = 1;
101     dfn[u] = ++idc;
102     fprintf( stderr, "[" );
103     fprintf( stderr, "%d", u );
104     for( int t=head[u]; t; t=next[t] ) {
105         int v=dest[t];
106         if( v==fat[u] ) continue;
107         fat[v] = u;
108         dfs(v);
109     }
110     sgn[++idc] = -1;
111     fprintf( stderr, "]" );
112 }
113 Node *build( int lf, int rg ) {
114     Node *nd = ++tail;
115     nd->lf=lf, nd->rg=rg;
116     if( lf==rg ) {
117         nd->init( sgn[lf] );
118     } else {
119         int mid=(lf+rg)>>1;
120         nd->ls = build( lf, mid );
121         nd->rs = build( mid+1, rg );
122         nd->update();
123     }
124     fprintf( stderr, "[%d,%d] a=%2d e=%d v[0~6] = %2d %2d %2d %2d %2d %2d %2d\n",
125             lf, rg, nd->a, nd->e, nd->v[0], nd->v[1],
126             nd->v[2], nd->v[3], nd->v[4], nd->v[5], nd->v[6] );
127     return nd;
128 }
129 int main() {
130     scanf( "%d", &n );
131     for( int i=1,u,v; i<n; i++ ) {
132         scanf( "%d%d", &u, &v );
133         adde( u, v );
134         adde( v, u );
135     }
136     for( int i=1; i<=n+n+n; i++ )
137         fprintf( stderr, "%d", i%10 );
138     fprintf( stderr, "\n" );
139     fat[1] = 0;
140     dfs(1);
141     fprintf( stderr, "\n" );
142     root = build( 1, idc );
143     scanf( "%d", &m );
144     for( int i=1,u; i<=m; i++ ) {
145         char ch[10];
146         scanf( "%s\n", ch );
147         if( ch[0]==‘G‘ ) {
148             printf( "%d\n", root->a );
149         } else {
150             scanf( "%d", &u );
151             root->reverse(dfn[u]);
152         }
153     }
154 }

另一种做法大概是用点分,然后用堆维护最值.

时间: 2024-12-29 06:38:53

bzoj 1095 括号序列求两点距离的相关文章

[BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)

[BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个合法的括号序列. 2.若A是合法的括号序列,则(A)是合法的括号序列. 3.若A,B是合法的括号序列,则AB是合法的括号序列. 我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右 括号,现在他得到了一个长度为2n的括号序列,给了你m个信息,第i 个信息形如ai,bi,表示match

bzoj 2209 括号序列

反转操作 + 翻转操作 = 对称操作 因为上面三个操作都是自己的逆操作,所以我们只需要实现对称操作和反转操作,就可以搞定翻转操作. 1 #include <cstdio> 2 #include <algorithm> 3 #define N 100010 4 using namespace std; 5 6 struct Node { 7 int siz, val, clf[2], crg[2], rtag, etag; 8 Node *ch[2], *par; 9 void up

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

2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1111  Solved: 541[Submit][Status][Discuss] Description Input 输入数据的第一行包含两个整数N和Q,分别表示括号序列的长度,以及操作的个数. 第二行包含一个长度为N的括号序列. 接下来Q行,每行三个整数t.x和y,分别表示操作的类型.操作的开始位置和操作的结 束位置,输入数据保证x不小于y.其中t=0表

【算法学习笔记】36.凸包 求最大两点距离 SJTU OJ 1244 Date A Live

Description 某助教有好多好多妹纸,其中不乏来自五道口与东川路等男子职业技术学校的.然而,遥远的距离让他不得不花费大量的时间奔波于众多城市之间.为了更好地安排自己的约会计划,他想知道最远的两只妹纸之间的距离是多少. Input Format 第一行有一个整数n,表示妹纸的数量. 接下来n行,每行两个实数x,y,表示妹纸的坐标(假定在一个平面直角坐标系上). 对于80%的数据,n<=2000 对于90%的数据,n<=10000 对于100%的数据,n<=100000 Output

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

http://www.lydsy.com/JudgeOnline/problem.php?id=2209 splay又犯逗........upd1那里的sum忘记赋值反............. 本题好神..首先发现将所有能匹配的消掉后一定是类似这样的))))((((,当然也有((((((这种情况 还有本题将查询的区间长度都看做偶数..... 如果能知道有多少个)和多少个(,那么答案就是 )的个数除以2取上界+(的个数除以2取上界 很简单吧...... 所以我们只需要在splay维护从左边连续的

【BZOJ 1095】 [ZJOI2007]Hide 捉迷藏

1095: [ZJOI2007]Hide 捉迷藏 Time Limit: 40 Sec  Memory Limit: 162 MB Submit: 1232  Solved: 501 [Submit][Status] Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达.游戏是这样进行的,孩子

[BZOJ]1095 Hide捉迷藏(ZJOI2007)

一道神题,两种神做法. Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达.游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯.在起初的时候,所有的灯都没有被打开.每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯

bzoj 1095 捉迷藏(线段树)

题外话 最近课程不是很紧,准备按AC率版切bz,争取一天一道题以上.然后我喜闻乐见的发现之前剩下的题基本都是数据结构>_<.蛋疼啊... Description 给定一棵树,每个节点要么是黑色,要么是白色,能执行两个操作:把某一个点取反色,返回距离最远的黑色点对. Solution 这题看起来链分治,边分治都可做,然后搜到了小岛的题解.发现了逼格更高的做法,看了曹钦翔的<数据结构的提炼与压缩>,跪烂了... 这题用到了dfs序的性质,也就是括号序列.. 定义一种对一棵树的括号编码.

初学DP(1) 黑书中的《括号序列》

题目:括号序列 定义如下规则序列(字符串): 1.空序列是规则序列: 2.如果S是规则序列,那么(S)和[S]也是规则序列: 3.如果A和B都是规则序列,那么AB也是规则序列: 例如,下面的字符串都是规则序列: (),    [],    (()),    ([]),    ()[()]; 而这几个就不是规则序列: (,    [,    )(,    ([]; 现在给出一些有'(',')','[',']'构成的序列,请添加少量的括号,得到一个规则的序列. 分析: 用s[i],s[j]表示字符串