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. MIUI 6的毛玻璃效果的技术实现(实时模糊)

    说说MIUI 6的毛玻璃效果的技术实现.   很久以前我们的文件夹打开和最近任务等几个地方就使用了毛玻璃效果,在技术上讲就是背景模糊.应该是比iOS 7的使用要早很多.不过那时候我们使用的是先对背景截 ...

  2. Containerpilot 配置文件模板

    { "consul": "{{ .CONSUL }}:8500", "logging": { "level": &quo ...

  3. Linux之常用命令

    1.cd命令 这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径.如: cd /root/Docements # 切换到 ...

  4. Broadcast总结 service

    有时候离开应用就会接收不到系统的广播是因为系统默认发送的广播都会有一个参数 ntent startIntent = new Intent();startIntent.putExtra("pk ...

  5. Spring依赖注入servlet会话监听器

    Spring提供了一个 “ContextLoaderListener” 监听器,以使 Spring 依赖注入到会话监听器. 在本教程中,通过添加一个 Spring 依赖注入一个bean 到会话监听器修 ...

  6. viewstamp replication: A new primary copy method to support highly-avaliable d

    为了提高服务能力或者服务稳定,往往需要把数据重复布署,也就是replication.重复带来的问题是,更新的时候会带来不一致.一种比较简单的方法是,在N台重复的机器里选一台作为主机,其他作备份,只能通 ...

  7. .NET中的Request

    获得浏览器中的URL 例:http://121.41.30.93:8010/ch/spell.aspx?id=58 Request.Url.PathAndQuery:/ch/spell.aspx?id ...

  8. sql标量值函数,将汉字转化为拼音,无音标

    USE [db_Test]GO SET ANSI_NULLS ONGO SET QUOTED_IDENTIFIER ONGO create function [dbo].[fn_GetPinyin]( ...

  9. PAT 1070 结绳(25)(代码)

    1070 结绳(25 分) 给定一段一段的绳子,你需要把它们串成一条绳.每次串连的时候,是把两段绳子对折,再如下图所示套接在一起.这样得到的绳子又被当成是另一段绳子,可以再次对折去跟另一段绳子串连.每 ...

  10. Jmeter If Controller中设置多个条件用“与”进行连接

    "${noteID}"!="NOT FOUND" && "${securitiesId}"!="0P00011FQ ...