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. cmd 命令相关

    计算相关进程数: tasklist|find /i "cmd.exe" 安装git的可以 tasklist|find /i "cmd.exe"  | wc -l

  2. EnumMap实现类

    从名字上看出来,EnumMap是为枚举类服务的,它的key不能为null,在创建它的时候,必须要指定一个枚举类,如: EnumMap enumMap = new EnumMap(Season.clas ...

  3. SearchEngine Note

    [SearchEngine Note] 1.查全率. 2.查准率. 3.查全率与查准率的关系. 4.四大系统. 5.权威性网页反向链接多.网页的平均出席为25.7,即平均每一个网页含有25.7个指向其 ...

  4. 精确除法:from __future__ import division

    在python中做除法运算,使用1/2运行结果为0,为取结果的整数部分 如果用1.0/2或1/2.0运行结果为0.5,按照浮点数的位数取结果 但是实际应用中我们需要取除法的精确结果,我们就可以在运行前 ...

  5. cin中函数的作用

    cin是istream类的对象,它是从标准输入设备(键盘)获取数据,程序中的变量通过流提取符">>"从流中提取数据.流提取符">>"从流 ...

  6. Windows系统之hosts文件

    对于Hosts文件相信很多Win7的系统用户会比较陌生,其实Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,所以功 ...

  7. mongo远程登录

    1. 进入数据库: use admin db.addUser("foo","foo"); ps:高版本用db.createUser创建. 2. 改配置 如/et ...

  8. 零基础学习hadoop到上手工作线路指导(中级篇)

    此篇是在零基础学习hadoop到上手工作线路指导(初级篇)的基础,一个继续总结. 五一假期:在写点内容,也算是总结.上面我们会了基本的编程,我们需要对hadoop有一个更深的理解: hadoop分为h ...

  9. vc通过webbrowser操作ie元素

    1>需要引用 webbrowser2.h,mshtml.h //m_web绑定的webbrowser的变量 CComQIPtr<IHTMLDocument2,&IID_IHTMLD ...

  10. Nginx 分析access日志文件

    Nginx Access Log日志统计分析常用命令 IP相关统计 统计IP访问量 awk '{print $1}' access.log | sort -n | uniq | wc -l 查看某一时 ...