题意:一棵树n个结点,每条边有0.1两种权值,每次询问权值为奇数的路径数目,或者改变某一条边的权值。

分析:这个题目很巧妙低利用了异或和的特性,dfs得到每个点到根结点的权值异或和,然后奇数则为1,偶数为0,异或和为0和1的点组成的路径权值和一定为奇数,询问结果就是0个数和1个数乘积2倍。

代码:

 #include <cstdio>
#include <iostream>
#include <vector>
#include <map>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#define pb push_back
#define mp make_pair #define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define sz(x) ((int)((x).size()))
#define pb push_back
#define in freopen("data.txt", "r", stdin);
#define bug(x) printf("Line : %u >>>>>>\n", (x));
#define inf 0x0f0f0f0f
using namespace std;
typedef pair<int, int> PII;
typedef map<string, int> MPS;
typedef long long LL; const int maxn = + ;
MPS mps; struct Edge {
int u, v, c;
Edge() {}
Edge(int u, int v, int c):u(u), v(v), c(c) {}
};
vector<Edge> edges;
vector<int> g[maxn]; int n, m, q, cnt;
int le[maxn], ri[maxn]; int idx(char *s) {
if(mps.count(s) == false)
mps[s] = ++cnt;
return mps[s];
} void add(int u, int v, int c) {
edges.pb(Edge(u, v, c));
edges.pb(Edge(v, u, c));
m = edges.size();
g[u].pb(m-);
g[v].pb(m-);
}
char sa[], sb[];
int cover[maxn<<], val[maxn], dep[maxn], ans[maxn<<];
void PushUp(int rt) {
ans[rt] = ans[rt<<]+ans[rt<<|];
}
//线段树的每个结点要初始化!!!! void PushDown(int l, int r, int rt) {
int m = (l+r)>>;
if(cover[rt]) {
cover[rt<<] ^= ;
cover[rt<<|] ^= ;
ans[rt<<] = m-l+-ans[rt<<];
ans[rt<<|] = r-m-ans[rt<<|];
cover[rt] = ;
}
}
void build(int l, int r, int rt) {
if(l == r) {
cover[rt] = ;
ans[rt] = val[l];
return;
}
cover[rt] = ;
int m = (l+r)>>;
build(lson);
build(rson);
PushUp(rt);
}
void update(int l, int r, int rt, int L, int R) {
if(L <= l && R >= r) {
cover[rt] ^= ;
ans[rt] = r-l+-ans[rt];
return;
} int m = (l+r)>>;
PushDown(l, r, rt);
if(L <= m)
update(lson, L, R);
if(R > m)
update(rson, L, R);
PushUp(rt);
}
void dfs(int u, int fa, int va) {
dep[u] = dep[fa] + ;
le[u] = ++cnt;
val[cnt] = va;
for(int i = ; i < (int)g[u].size(); i++) {
Edge e = edges[g[u][i]];
int v = e.v;
int c = e.c;
if(v == fa) continue;
dfs(v, u, c^va);
}
ri[u] = cnt;
}
int main() { int T;
int kase = ;
for(int t = scanf("%d", &T); t <= T; t++) {
scanf("%d", &n);
mps.clear();
cnt = ;
edges.clear();
for(int i = ; i <= n; i++) {
g[i].clear();
scanf("%s", sa);
idx(sa);
}
for(int i = ; i < n-; i++) {
int c, u, v;
scanf("%s%s%d", sa, sb, &c);
u = idx(sa);
v = idx(sb);
add(u, v, c);
}
scanf("%d", &q);
printf("Case #%d:\n", ++kase);
cnt = ;
dfs(, , );
build(, n, );
LL res = ;
while(q--) {
scanf("%s", sa);
if(sa[] == 'Q') {
res = (LL)(n-ans[])*ans[]*;
printf("%I64d\n", res);
} else {
int x;
scanf("%d", &x);
x--;
x <<= ;
int u = edges[x].u;
int v = edges[x].v;
if(dep[u] < dep[v]) swap(u, v);
update(, n, , le[u], ri[u]);
}
}
}
return ;
}

当然也有一种更复杂的方法,同Qtree4,可以拿来练手,感觉有点无聊。

HDU 5039 Hilarity的更多相关文章

  1. hdu 5039 线段树+dfs序

    http://acm.hdu.edu.cn/showproblem.php?pid=5039 给定一棵树,边权为0/1.m个操作支持翻转一条边的权值或者询问树上有多少条路径的边权和为奇数. 用树形df ...

  2. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  4. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  5. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  6. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  7. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

  8. hdu 4481 Time travel(高斯求期望)(转)

    (转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. HDU 3791二叉搜索树解题(解题报告)

    1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...

随机推荐

  1. 委托和事件[delegate and event]_C#

    委托和事件: 1. 委托:一个能够表示方法的数据类型:它将方法作为对象封装起来,允许在运行时间接地绑定一个方法调用. 2. 声明委托数据类型: public delegate  bool Greate ...

  2. makefile--编码修改-空格出现错误

    "makefile", line 40: make: 1254-055 Dependency line needs colon or double colon operator. ...

  3. [java学习笔记]java语言基础概述之内存的划分&堆和栈

    1.内存的划分 1.寄存器 cpu处理 2.本地方法区 和所在系统相关 3.方法区 方法加载进内存,其实就是开辟了一块该方法的方法区 方法区中还可以有静态区,用于存放静态变量(类变量) 4.栈内存 5 ...

  4. Java多线程(四) 线程池

    一个优秀的软件不会随意的创建.销毁线程,因为创建和销毁线程需要耗费大量的CPU时间以及需要和内存做出大量的交互.因此JDK5提出了使用线程池,让程序员把更多的精力放在业务逻辑上面,弱化对线程的开闭管理 ...

  5. 关于C++引用的一些注意点

    C++的引用首先跟指针的最大区别就是引用不是一个对象,而指针是一个对象:其次引用在其定义时就要初始化,而指针可以不用. ; int &rval = val; 此时rval就绑定了val,其实就 ...

  6. 快速解码base64和utf-8的ASCII编码和URL解码

    看论坛上总是有人发乱七八糟的文字,根本看不懂,用下面的方法解密一下. 只要有浏览器的开发者工具就行了. UTF-16解码 console.log("\u5475\u5475") U ...

  7. LCD/LED/OLED/等离子显示器区别

    LCD液晶显示器: LCD(Liquid Crystal Display),其构造是在两片平行的玻璃当中放置液态的晶体(液晶),在玻璃后面,以CCFL冷光灯管(类似日光灯)作背光源.液晶的成像原理可以 ...

  8. wxPython 基本框架与运行原理 -- App 与 Frame

    <wxPython in Action> chapter 1.2 笔记 wxPython 是 wxWidgets 的 Python 实现,“w” for Microsoft Windows ...

  9. 图像处理-07-图像的轮廓提取-Robert算子

    图像的轮廓提取-Robert算子 图像的边缘:周围像素灰度有阶跃变化或“屋顶”变化的那些像素的集合,边缘广泛存在于物体与背景之间.物体与物体之间,基元与基元之间,是图像分割的重要依据. 物体的边缘是由 ...

  10. php的异步框架

    swoole目前已被多家移动互联网.物联网.网络游戏.手机游戏企业使用,替代了C++.Java等复杂编程语言来实现网络服务器程序. 使用PHP+Swoole,开发效率可以大大提升.官方提供了基于swo ...