传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1095

首先我必须得感谢yzjc的细心讲解和某岛的题解,如果没有的话我相信我现在还在纠结。。不过某岛的上面写的后面我没有看懂,然后yzjc就给我讲了一个可看的合并。不过由于我自己写的比较的丑,在bzoj的跑的还是比较的慢。。。

首先这道题需要转成一个括号序列,然后我们可以发现两个点之间的路径可以通过某种加法得到,假设向下走为+1, 向上走是 -1,并且我们在这个序列中加入原来的点,也就是一个点在序列中会有三个点表示,这个时候发现两点之间的距离是可以分为两段——一段向上的-1的然后一段+1的(一段中出现的可匹配的括号已经合并了),答案就是前段的-1的和的相反数,加上后面的+1的和。 而如果要使值最大,在不考虑点颜色的情况下,那么这个分割点的应该是lca,不过这个不重要,因为需要找到的是一个值最大,lca具体事哪个位置并不重要

那么考虑答案合并的时候,对于一个答案,那么他可以被lson的答案和rson的答案更新,同时还有可能有中间的一段。而中间一段的分割点可能在中间点的左边或者右边。在左边的时候那么就是左边的后缀的最大的答案加上右边最大的前缀和(相当于右边一定是向下的一段) 在右边的时候就是左边后缀最小和的绝对值+右边前缀答案最大值。然后前缀后缀和参照最大字段和,然后最大答案前缀和后缀类似,前缀的话是左边的前缀,左边的全局答案(新的量)+右边的前缀最大和,左边的和的相反数家右边的前缀最大答案。而刚刚提到的全局答案指的是从区间左边到区间右边整个的答案类似全局的和。 而这个更新方式相当于是找个最大值(因为找lca相当于找一个最大值), 参考一下前面的答案合并就好了

不知道说了这么多好像有点乱= = 不过确实他就是这么的乱。 然后考虑颜色,黑点0,白点INF表示不可取,边的前缀答案和后缀答案及其相关量也是INF,因为边不能单独存在而是要必须要黑点最为端点

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = ;
const int INF = 0x3f3f3f3f; struct node {
int data, ans, sum, lsum, rsum, lans, rans;
node *l ,*r;
}tr[maxn * ]; int trne = ;
node* root; void test(node* x, int l, int r) {
cout << l <<" "<< r <<" "<< x-> data <<" " << x-> ans <<" "<< x-> sum <<" "<< x-> lsum <<" "<< x-> rsum <<" "<<x-> lans <<" "<< x-> rans <<" "<< endl;
if(l ^ r) {
int mid = (l + r) >> ;
test(x-> l, l, mid), test(x-> r, mid + , r);
}
} node* build(int l, int r) {
node* now = tr + trne ++;
if(l ^ r) {
int mid = (l + r) >> ;
now-> l = build(l, mid);
now-> r = build(mid + , r);
}
return now;
} void update(node *x) {
if(x-> l) {
x-> data = max(max(x-> l-> data, x-> r-> data), max(x-> l-> rans + x-> r-> lsum, -x-> l-> rsum + x-> r-> lans));
x-> ans = max(x-> l-> ans + x-> r-> sum, -x-> l-> sum + x-> r-> ans);
x-> sum = x-> l-> sum + x-> r-> sum;
x-> lsum = max(x-> l-> lsum, x-> l-> sum + x-> r-> lsum);
x-> rsum = min(x-> r-> rsum, x-> r-> sum + x-> l-> rsum);
x-> lans = max((x-> l-> lans), max(x-> l-> ans + x-> r-> lsum, -x-> l-> sum + x-> r-> lans));
x-> rans = max((x-> r-> rans), max(x-> l-> rans + x-> r-> sum, -x-> l-> rsum + x-> r-> ans));
}
} void insert(node* x, int l, int r, int v, int pos, int col) {
if(l == r) {
x-> ans = x-> data = x-> sum = x-> lsum = x-> rsum = x-> lans = x-> rans = ;
x-> data = -INF;
if(!v) {
if(col == ) x-> lsum = -INF, x-> rsum = INF, x-> lans = -INF, x-> rans = -INF, x-> ans = -INF, x-> data = -INF;
}
else {
x-> sum = v; x-> ans = abs(v); x-> data = abs(v);
if(v > ) x-> lsum = -INF, x-> rsum = INF, x-> lans = x-> rans = -INF, x-> data = -INF, x-> ans = ;
else x-> rsum = INF, x-> lsum = -INF, x-> lans = x-> rans = -INF, x-> data = -INF, x-> ans = ;
}
}
else {
int mid = (l + r) >> ;
if(pos <= mid) insert(x-> l, l, mid, v, pos, col);
else insert(x-> r, mid + , r, v, pos, col);
update(x);
}
} struct edge {
int t; edge* next;
}e[maxn * ], *head[maxn]; int ne = ; void addedge(int f, int t) {
e[ne].t = t, e[ne].next = head[f], head[f] = e + ne ++;
} int in[maxn], map[maxn], out[maxn], c[maxn], num = , n, m;
int cnt = ; void dfs(int x, int fa) {
in[x] = num ++, map[x] = num ++;
for(edge* p = head[x]; p; p = p-> next) {
if(p-> t != fa) dfs(p-> t, x);
}
out[x] = num ++;
} int int_get() {
int x = ; char c = (char)getchar();
while(!isdigit(c) && c != '-') c = (char)getchar();
bool f = ;
if(c == '-') c = (char)getchar(), f = ;
while(isdigit(c)) {
x = x * + (int)(c - '');
c = (char)getchar();
}
if(f) x = -x;
return x;
} void read() {
n = int_get(); cnt = n;
for(int i = ; i < n; ++ i) {
int u, v; u = int_get(), v = int_get();
addedge(u, v), addedge(v, u);
}
for(int i = ; i <= n; ++ i) c[i] = ;
dfs(, ); num -= ; root = build(, num);
for(int i = ; i <= n; ++ i) {
insert(root, , num, , map[i], c[i]);
if(i != ) {
insert(root, , num, , in[i], );
insert(root, , num, -, out[i], );
}
}
} void sov() {
m = int_get();
while(m --) {
char s[]; scanf("%s", s + );
if(s[] == 'G') {
if(cnt <= ) printf("%d\n", cnt - );
else printf("%d\n", root-> data);
}
if(s[] == 'C') {
int x = int_get();
if(c[x]) cnt --;
else cnt ++;
c[x] = !c[x];
insert(root, , num, , in[x], );
insert(root, , num, , map[x], c[x]);
insert(root, , num, -, out[x], );
}
}
//test(root, 1, num); cout << endl;
} int main() {
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
read(); sov();
//update(root-> r);
return ;
}

bzoj 1095的更多相关文章

  1. bzoj 1095 Hide 捉迷藏 - 动态点分治 -堆

    Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双 ...

  2. BZOJ 1095: [ZJOI2007]Hide 捉迷藏

    Description 一棵树,支持两个操作,修改一个点的颜色,问树上最远的两个白点距离. Sol 动态点分治. 动态点分治就是将每个重心连接起来,形成一个跟线段树类似的结构,当然它不是二叉的... ...

  3. bzoj 1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1095 [题意] 给定一棵树,树上颜色或白或黑而且可以更改,多个询问求最远黑点之间的距离 ...

  4. BZOJ.1095.[ZJOI2007]捉迷藏(线段树 括号序列)

    BZOJ 洛谷 对树DFS得到括号序列.比如这样一个括号序列:[A[B[E][F[H][I]]][C][D[G]]]. 那比如\(D,E\)间的最短距离,就是将\(D,E\)间的括号序列取出:][[] ...

  5. bzoj 1095 括号序列求两点距离

    大致题意: 给一棵树,每个节点最开始都是黑色,有两种操作,1.询问树中相距最远的一对黑点的距离 2.反转一个节点的颜色 一种做法: 建立出树的括号序列,类似这样: [A[B][C]],所以长度为3*n ...

  6. 【BZOJ 1095】 1095: [ZJOI2007]Hide 捉迷藏 (括号序列+线段树)

    1095: [ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏 ...

  7. BZOJ 1095: [ZJOI2007]Hide 捉迷藏(线段树维护括号序列)

    这个嘛= =链剖貌似可行,不过好像代码长度很长,懒得打(其实是自己太弱了QAQ)百度了一下才知道有一种高大上的叫括号序列的东西= = 岛娘真是太厉害了,先丢链接:http://www.shuizilo ...

  8. [BZOJ]1095 Hide捉迷藏(ZJOI2007)

    一道神题,两种神做法. Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特 ...

  9. 【bzoj 1095】[ZJOI2007]Hide 捉迷藏

    题目链接: TP 题解: 样例好良心,调样例3h一A…… 细节好多……诸如没完没了的pop和push……搞得头都大了. 同情zzh……调了整一天了. 动态点分治裸题……果然每个“裸题”打起来都跟shi ...

随机推荐

  1. php socket简单原理及实现笔记

    1.什么是socket? socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,连接的一端称为一个socket. 因此socket运行是置少有2个端组成,一个为服务端一个为客户端(客户端 ...

  2. 【leetcode】519. Random Flip Matrix

    题目如下: You are given the number of rows n_rows and number of columns n_cols of a 2D binary matrix whe ...

  3. security 页面测试

    <!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content=& ...

  4. 【Flutter学习】之绘画实例(二)

    一,画路径 - drawPath(Path path, Paint paint)  Path 主要有方法如下: 直接描述路径的方法还可以细分为两组:添加子图形和画线(直线或曲线) addXXX() - ...

  5. ylbtech-公司-滴滴出行:滴滴出行

    ylbtech-公司-滴滴出行:滴滴出行 滴滴出行是涵盖出租车. 专车.  滴滴快车.  顺风车. 代驾及 大巴等多项业务在内的一站式出行平台,2015年9月9日由“滴滴打车”更名而来. 2月1日起, ...

  6. VTemplate模板引擎的使用--高级篇

    VTemplate模板引擎的使用--高级篇 在网站中,经常会有某个栏目的数据在多个页面同时使用到.比如新闻网站或电子商务网站的栏目列表,几乎在很多页面都会显示栏目导航.对于这种多个页面同时使用到的“数 ...

  7. Nginx网络架构实战学习笔记(四):nginx连接memcached、第三方模块编译及一致性哈希应用

    文章目录 nginx连接memcached 第三方模块编译及一致性哈希应用 总结 nginx连接memcached 首先确保nginx能正常连接php location ~ \.php$ { root ...

  8. LOJ #103. 子串查找 (Hash)

    题意 给定两个字符串 \(A\) 和 \(B\),求 \(B\) 在 \(A\) 中的出现次数. 思路 这是一道 \(KMP\) 的模板题. 不过 \(Hash\) 是个好东西,可以用 \(Hash\ ...

  9. Rust <7>:数据结构==>链表

    enum List { Cons(u64, Box<List>), NULL, } impl List { fn new() -> List { List::NULL } fn pr ...

  10. JVM(1):Java 类的加载机制

    原文出处: 纯洁的微笑 java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang. ...