bzoj 1095 括号序列求两点距离
2015-06-15 20:28
288 查看
大致题意: 给一棵树,每个节点最开始都是黑色,有两种操作,1.询问树中相距最远的一对黑点的距离 2.反转一个节点的颜色
一种做法:
建立出树的括号序列,类似这样: [A[B][C]],所以长度为3*n
假如我们要询问AC间的距离,提取出中间的括号:[]],匹配消去后得到],其长度就是距离.
现在我们要做的就是修改点的状态,并且动态维护答案.要用到一些求与绝对值相关的式子的技巧.
View Code
另一种做法大概是用点分,然后用堆维护最值.
一种做法:
建立出树的括号序列,类似这样: [A[B][C]],所以长度为3*n
假如我们要询问AC间的距离,提取出中间的括号:[]],匹配消去后得到],其长度就是距离.
现在我们要做的就是修改点的状态,并且动态维护答案.要用到一些求与绝对值相关的式子的技巧.
/************************************************************** Problem: 1095 User: idy002 Language: C++ Result: Accepted Time:2176 ms Memory:55548 kb ****************************************************************/ #include <cstdio> #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define N 100010 #define M N<<1 #define oo 0x3f3f3f3f #define fprintf(...) struct Node { int v[7], c, e, a; int lf, rg; Node *ls, *rs; void init( int type ) { if( type==0 ) { a = 0; e = false; c = 1; for( int t=0; t<7; t++ ) v[t]=0; } else if( type==-1 ) { // (1,0) a = -1; e = true; c = 0; v[1] = v[3] = v[6] = v[2] = v[5] = 1; v[0] = v[4] = -1; } else { // (0,1) a = -1; e = true; c = 0; v[1] = v[3] = v[6] = v[0] = v[4] = 1; v[2] = v[5] = -1; } } void update() { e = ls->e && rs->e; v[5] = ls->v[5] + rs->v[5]; v[4] = ls->v[4] + rs->v[4]; v[6] = max( ls->v[6]+rs->v[4], ls->v[5]+rs->v[6] ); if( !ls->e && !rs->e ) { v[0] = max( ls->v[0], ls->v[4]+rs->v[0] ); v[1] = max( ls->v[1], max( ls->v[6]+rs->v[0], ls->v[5]+rs->v[1] ) ); v[2] = max( rs->v[2], ls->v[2]+rs->v[5] ); v[3] = max( rs->v[3], max( ls->v[3]+rs->v[4], ls->v[2]+rs->v[6] ) ); a = max( max(ls->v[3]+rs->v[0],ls->v[2]+rs->v[1]), max(ls->a,rs->a) ); } else if( !ls->e ) { v[0] = ls->v[0]; v[1] = ls->v[1]; v[2] = ls->v[2]+rs->v[5]; v[3] = max( ls->v[3]+rs->v[4], ls->v[2]+rs->v[6] ); a = ls->a; } else if( !rs->e ) { v[0] = ls->v[4]+rs->v[0]; v[1] = max( ls->v[6]+rs->v[0], ls->v[5]+rs->v[1] ); v[2] = rs->v[2]; v[3] = rs->v[3]; a = rs->a; } else { a = -1; } } void reverse( int pos ) { if( lf==rg ) { if( c ) { c = 0; a = -1; e = true; } else { c = 1; a = 0; e = false; } return; } int mid=(lf+rg)>>1; if( pos<=mid ) ls->reverse(pos); else rs->reverse(pos); update(); } }pool[N*3*3], *tail=pool, *root; int n, m; int head , dest[M], next[M], etot; int dfn , sgn[N*3], fat , idc; void adde( int u, int v ) { etot++; next[etot] = head[u]; dest[etot] = v; head[u] = etot; } void dfs( int u ) { sgn[++idc] = 1; dfn[u] = ++idc; fprintf( stderr, "[" ); fprintf( stderr, "%d", u ); for( int t=head[u]; t; t=next[t] ) { int v=dest[t]; if( v==fat[u] ) continue; fat[v] = u; dfs(v); } sgn[++idc] = -1; fprintf( stderr, "]" ); } Node *build( int lf, int rg ) { Node *nd = ++tail; nd->lf=lf, nd->rg=rg; if( lf==rg ) { nd->init( sgn[lf] ); } else { int mid=(lf+rg)>>1; nd->ls = build( lf, mid ); nd->rs = build( mid+1, rg ); nd->update(); } fprintf( stderr, "[%d,%d] a=%2d e=%d v[0~6] = %2d %2d %2d %2d %2d %2d %2d\n", lf, rg, nd->a, nd->e, nd->v[0], nd->v[1], nd->v[2], nd->v[3], nd->v[4], nd->v[5], nd->v[6] ); return nd; } int main() { scanf( "%d", &n ); for( int i=1,u,v; i<n; i++ ) { scanf( "%d%d", &u, &v ); adde( u, v ); adde( v, u ); } for( int i=1; i<=n+n+n; i++ ) fprintf( stderr, "%d", i%10 ); fprintf( stderr, "\n" ); fat[1] = 0; dfs(1); fprintf( stderr, "\n" ); root = build( 1, idc ); scanf( "%d", &m ); for( int i=1,u; i<=m; i++ ) { char ch[10]; scanf( "%s\n", ch ); if( ch[0]=='G' ) { printf( "%d\n", root->a ); } else { scanf( "%d", &u ); root->reverse(dfn[u]); } } }
View Code
另一种做法大概是用点分,然后用堆维护最值.
相关文章推荐
- Platform设备驱动
- JS显示动态显示当前时间代码
- 黑马程序员——Java基础之函数与数组
- Picture控件显示jpg
- 十、迭代器和组合模式
- 【Scala】高阶函数和柯里化
- 新手学习编程的最佳方式是什么?
- Android: 一个两点触控的案例
- 《编程珠玑》阅读小记(9) — 取样问题
- oracle中rowid解决数据重复的问题
- WebX学习二——URL请求流程分析
- 【Scala】头等函数与函数即对象
- poj2509---抽k根烟就换一支,求能抽烟的总数
- 《编程珠玑》阅读小记(9) — 取样问题
- Android布局优化之Merge Include ViewStub使用与源码分析
- 文本编辑器vi和vim(2)
- mac 下查找文件以及文件夹
- 【Scala】单例对象与伴生对象
- 大数据时代的技术hive:hive的数据类型和数据模型
- STL用法