码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1095 括号序列求两点距离

时间:2015-06-15 21:47:22      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:

 

大致题意: 给一棵树,每个节点最开始都是黑色,有两种操作,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 }
View Code

 

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

 

bzoj 1095 括号序列求两点距离

标签:

原文地址:http://www.cnblogs.com/idy002/p/4579117.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!