http://acm.hdu.edu.cn/showproblem.php?pid=5039

给定一棵树,边权为0/1。m个操作支持翻转一条边的权值或者询问树上有多少条路径的边权和为奇数。

用树形dfs出每个点到根的路径上边权和是否为奇数;

由于翻转一个边只会连带影响其下的子节点,所有线段树记录更新区间,odd记录到根的路径上边权和为奇数的个数,每次只需更新和查询odd,没有lazy会超时

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
#define MI(x,y) ((x+y)>>1)
const int maxn = 30010;
int head[maxn],l[maxn],r[maxn],val[maxn];
int n,m,tot,idx;
struct edge{
int u,v,f,next;
}ed[maxn<<1];
map<string , int> hash;
struct tree{
int l,r,odd,// odd为到根的路径上边权和为奇数的个数
lazy;// lazy控制翻转次数,翻转偶数次相当于没有翻转
}d[maxn<<2];
void add(int u,int v,int f)
{
ed[tot] = (edge){u,v,f,head[u]},head[u] = tot++;
ed[tot] = (edge){v,u,f,head[v]},head[v] = tot++;
}
void dfs(int u,int f,int fa)
{
idx++;
val[idx] = f;
l[u] = idx;
for(int i = head[u];i != -1;i = ed[i].next){
if(ed[i].v != fa){
dfs(ed[i].v,f ^ ed[i].f,u);
}
}
r[u] = idx;
}
void up(int root)
{
d[root].odd = d[L(root)].odd + d[R(root)].odd;
}
void build(int l,int r,int root)
{
d[root] = (tree){l,r,val[l],0};
if(l == r)
return ;
int mid = MI(l,r);
build(l,mid,L(root));
build(mid+1,r,R(root));
up(root);
}
void down(int root) {
if (d[root].lazy) {
d[L(root)].lazy ^= 1;// 翻转偶数次相当于没翻转,所以不需要更新其子节点
d[R(root)].lazy ^= 1;
d[L(root)].odd = d[L(root)].r - d[L(root)].l + 1 - d[L(root)].odd;
d[R(root)].odd = d[R(root)].r - d[R(root)].l + 1 - d[R(root)].odd;
d[root].lazy = 0;
}
}
void update(int l, int r, int root)
{
if (d[root].l == l && d[root].r == r) {
d[root].odd = d[root].r - d[root].l + 1 - d[root].odd;
d[root].lazy ^= 1;
return;
}
down(root);
int mid = MI(d[root].l,d[root].r);
if (r <= mid)
update(l, r, L(root));
else if (l > mid)
update(l, r, R(root));
else {
update(l, mid, L(root));
update(mid + 1, r, R(root));
}
up(root);
} int main()
{
int _;
RD(_);
string str,rts;
char q[2];
for(int cas = 1;cas <= _;++cas){
printf("Case #%d:\n", cas);
hash.clear();
RD(n);
for(int i = 1;i <= n;++i){
cin>>str;
hash[str] = i;
head[i] = -1;
}
tot = 0;
int u,v,f;
for(int i = 1;i < n;++i){
cin>>str>>rts;
RD(f);
add(hash[str],hash[rts],f);
}
idx = 0;
dfs(1,0,0);
build(1,n,1);
RD(m);
while(m--){
scanf("%s",q);
if(q[0] == 'Q'){
printf("%d\n",d[1].odd * (n - d[1].odd) * 2);
}else{
RD(f);
f = (f-1)<<1;// 边的记录用例两单位的ed
u = ed[f].u,v = ed[f].v;
if(l[u] > l[v])
update(l[u],r[u],1);
else
update(l[v],r[v],1);
}
}
}
return 0;
}

hdu 5039 线段树+dfs序的更多相关文章

  1. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  2. HDU 5692 线段树+dfs序

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  3. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  4. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  5. 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序

    题目大意 ​ Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...

  6. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  7. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

  8. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  9. 【BZOJ-3306】树 线段树 + DFS序

    3306: 树 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 792  Solved: 262[Submit][Status][Discuss] De ...

随机推荐

  1. 输入N组父子对,求父子对所组成的二叉树的高度----17年某公司的笔试题

    题目的大致意思如下: 输入N组数,一组数代表一个父子对(如,0 1,0代表父节点,1代表子节点),求这N组数所组成的二叉树的高度: 例如: 输入:6  0 1  0 2  1 3  1 4  2 5 ...

  2. 解决:Invalid character found in method name. HTTP method names must be tokens

      阿里云上弄了一个tomcat,经常半夜发送崩溃,查看日志发现这个东西,查阅资料发现是Tomcat的header缓冲区大小不够,只需要在server.xml中增加maxHttpHeaderSize字 ...

  3. CentOS 7安装配置Redis数据库

    Redis源码获取 1.进入Redis官网获取Redis最新稳定版下载地址 2.通过wget命令下载 Redis 源代码.   Redis编译 1.通过tar -xvf redis-3.0.2.tar ...

  4. ssh-keygen生成私钥和公钥

    ssh-keygen生成私钥和公钥 例: 用户名:root 服务器地址:192.168.1.10 生成:ssh-keygen -t rsa -b 4096 -C“root@192.168.1.10” ...

  5. richface的配置、用法介绍和注意事项

    richface的配置.用法介绍和注意事项一.RichFaces (3.1.x) 技术需求 1.JDK 1.5 或更高版本: 2.支持的 JSF 实现: Sun JSF 1.1 RI - 1.2 My ...

  6. 基于快速排序的数组划分:2组 3组 K组(sort color)大小写排序 · Partition Array

    2组: [抄题]: 给出一个整数数组 nums 和一个整数 k.划分数组(即移动数组 nums 中的元素),使得: 所有小于k的元素移到左边 所有大于等于k的元素移到右边 返回数组划分的位置,即数组中 ...

  7. php加速缓存器opcache,apc,xcache,eAccelerator

    一.opcache opcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能, 存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销.   PHP 5. ...

  8. count(distinct) 与group by 浅析

    x在传统关系型数据库中,group by与count(distinct)都是很常见的操作.count(distinct colA)就是将colA中所有出现过的不同值取出来,相信只要接触过数据库的同学都 ...

  9. Django之XSS攻击

    一.什么是XSS攻击 xss攻击:----->web注入    xss跨站脚本攻击(Cross site script,简称xss)是一种“HTML注入”,由于攻击的脚本多数时候是跨域的,所以称 ...

  10. DB2中的数据类型

    DB2中的数据类型DB2内置数据类型可以分成数值型(numeric).字符串型(character string).图形字符串(graphic string).二进制字符串型(binary strin ...