hdu 5039 线段树+dfs序
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序的更多相关文章
- S - Query on a tree HDU - 3804 线段树+dfs序
S - Query on a tree HDU - 3804 离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...
- HDU 5692 线段树+dfs序
Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意 Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- 【BZOJ-3306】树 线段树 + DFS序
3306: 树 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 792 Solved: 262[Submit][Status][Discuss] De ...
随机推荐
- js中怎么写自执行函数
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 岭回归和lasso回归(转)
回归和分类是机器学习算法所要解决的两个主要问题.分类大家都知道,模型的输出值是离散值,对应着相应的类别,通常的简单分类问题模型输出值是二值的,也就是二分类问题.但是回归就稍微复杂一些,回归模型的输出值 ...
- mysql转型
1.将Int 转为varchar经常用 concat函数,比如concat(8,’0′) 得到字符串 ’80′2.将varchar 转为Int 用 cast(a as signed) a为varcha ...
- Python3 tuple 函数
Python3 tuple 函数 Python3 内置函数 描述 tuple 函数将列表转换为元组.. 语法 以下是 tuple 的语法: tuple( seq ) 参数 seq -- 要转换为元组 ...
- eclipse搭建struts2环境及所遇到的问题
最近几天一直在搭建struts2框架,本身struts2框架的搭建是非常简单的,但不知道为什么最近就是总是报错,报了一大串的错 首先就是每次在类的根路径下创建struts.xml时,就报错,也不知道为 ...
- TZOJ 5279 马拉松比赛(广搜)
描述 有一块矩形的海域,其中有陆地也有海洋,这块海域是CSUFT_ACM集训队的训练基地,这一天,昌神说要集训队的队员不能总是训练,于是昌神提出了中南林ACM集训队第一场环陆马拉松比赛,顾名思义就是围 ...
- jquery获取当前屏幕宽度
参考文章 <script type="text/javascript"> $(document).ready(function() { alert($(window). ...
- 乱序字符串anagrams
[抄题]: 给出一个字符串数组S,找到其中所有的乱序字符串(Anagram).如果一个字符串是乱序字符串,那么他存在一个字母集合相同,但顺序不同的字符串也在S中. 对于字符串数组 ["lin ...
- c语言定义函数指针和typedef简写
二种方法来定义函数指针 #include<stdio.h> #include<stdlib.h> #include<Windows.h> int add(int a ...
- 如何在ecplise中配置maven以及ecplise访问本地仓库
1.m2e的插件 因为使用ecplise版本比较高,所以它自带了maven的插件,但是我们希望可以使用我们自己指定的maven.配置步骤如下: ecplise--->preperences下,点 ...