hdu 4857 Little Devil I
http://acm.hdu.edu.cn/showproblem.php?pid=4897
题意:给你一棵树,边的颜色要么为白色,要么为黑色,初始每条边为白色,有三种操作
1、将u-v链上面的所有边的颜色翻转2、将u-v链上面所有邻接的边翻转(边上只有一个点在链上面)3、询问u->v上面有多少黑色的边树链剖分,线段树维护4个信息:
按dfs序建立线段树后,如果线段树内节点的区间为[l,r],则此节点维护树上dfs序[l,r]内的父边的信息
父边指 点与父节点之间的边
sum0:节点的父边属于重链且颜色为白色 的边数
sum1:节点的父边属于重链且颜色为黑色 的边数
rev1:节点的父边颜色是否被操作1取反 (实际只会用到属于轻链的边)
rev2:节点的子树中,与节点直接相连的属于轻链边 是否被操作2取反
操作1:直接取反,交换sum0和sum1,维护标记rev1
细节:最后u和v(dep[u]<dep[v])汇集到一条重链的时候,最后一次操作不包括u,因为点代表的是父边的信息
操作2:一条链的相邻边,除了对链上的点维护rev2操作外,
链最顶端的点如果是其父节点的重儿子,需要修改它的rev1
路径上每条重链最底端的点,如果它有重儿子,需要修改它重儿子的rev1
因为标记rev2只维护轻链
操作3:重链直接查,轻链呢?
在树链剖分往上跳的时候,跳轻链一定是只跳一条边
假设这条边连接了节点u和v,dep[u]<dep[v]
如果rev2[u]^rev2[v]^rev1[v] 为 true,则这条边为黑色
clj的题就是好哇!!!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm> using namespace std; #define N 100001 int n; int front[N],nxt[N<<],to[N<<],tot; int siz[N],dep[N],fa[N];
int bl[N],son[N];
int id[N],dy[N],cnt; bool big[N]; int sum0[N<<],sum1[N<<];
bool rev1[N<<],rev2[N<<]; int ans; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void dfs1(int x)
{
siz[x]=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x])
{
fa[to[i]]=x;
dep[to[i]]=dep[x]+;
dfs1(to[i]);
siz[x]+=siz[to[i]];
}
} void dfs2(int x,int top)
{
bl[x]=top;
id[x]=++cnt;
dy[cnt]=x;
int y=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && siz[to[i]]>siz[y]) y=to[i];
if(y)
{
son[x]=y;
big[y]=true;
dfs2(y,top);
}
else return;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && to[i]!=y) dfs2(to[i],to[i]);
} void down1(int k)
{
rev1[k<<]^=;
swap(sum0[k<<],sum1[k<<]);
rev1[k<<|]^=;
swap(sum0[k<<|],sum1[k<<|]);
rev1[k]^=;
} void down2(int k)
{
rev2[k<<]^=;
rev2[k<<|]^=;
rev2[k]^=;
} void Reverse(int k,int l,int r,int opl,int opr,int ty)
{
if(l>=opl && r<=opr)
{
if(ty==)
{
swap(sum1[k],sum0[k]);
rev1[k]^=;
}
else rev2[k]^=;
return;
}
int mid=l+r>>;
if(rev1[k]) down1(k);
if(rev2[k]) down2(k);
if(opl<=mid) Reverse(k<<,l,mid,opl,opr,ty);
if(opr>mid) Reverse(k<<|,mid+,r,opl,opr,ty);
if(ty==)
{
sum1[k]=sum1[k<<]+sum1[k<<|];
sum0[k]=sum0[k<<]+sum0[k<<|];
}
} int get_lca(int u,int v)
{
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
u=fa[bl[u]];
}
return dep[u]<dep[v] ? u : v;
} bool point_query(int k,int l,int r,int x,int ty)
{
if(l==r) return ty== ? rev1[k] : rev2[k];
if(rev1[k]) down1(k);
if(rev2[k]) down2(k);
int mid=l+r>>;
if(x<=mid) return point_query(k<<,l,mid,x,ty);
return point_query(k<<|,mid+,r,x,ty);
} void query(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr)
{
ans+=sum1[k];
return;
}
if(rev1[k]) down1(k);
if(rev2[k]) down2(k);
int mid=l+r>>;
if(opl<=mid) query(k<<,l,mid,opl,opr);
if(opr>mid) query(k<<|,mid+,r,opl,opr);
} void solve(int ty,int u,int v)
{
if(ty==)
{
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
Reverse(,,n,id[bl[u]],id[u],);
u=fa[bl[u]];
}
if(dep[u]>dep[v]) swap(u,v);
if(u!=v) Reverse(,,n,id[u]+,id[v],);
}
else if(ty==)
{
int lca=get_lca(u,v);
if(lca!=u && lca!=v)
{
if(big[lca]) Reverse(,,n,id[lca],id[lca],);
}
else
{
if(dep[u]>dep[v]) swap(u,v);
if(big[u]) Reverse(,,n,id[u],id[u],);
}
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
if(son[u]) Reverse(,,n,id[son[u]],id[son[u]],);
Reverse(,,n,id[bl[u]],id[u],);
u=fa[bl[u]];
}
if(dep[u]>dep[v]) swap(u,v);
if(son[v]) Reverse(,,n,id[son[v]],id[son[v]],);
Reverse(,,n,id[u],id[v],);
}
else
{
ans=;
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
query(,,n,id[bl[u]],id[u]);
ans+=point_query(,,n,id[bl[u]],)^point_query(,,n,id[fa[bl[u]]],)^point_query(,,n,id[bl[u]],);
u=fa[bl[u]];
}
if(dep[u]>dep[v]) swap(u,v);
if(u!=v) query(,,n,id[u]+,id[v]);
printf("%d\n",ans);
}
} void build(int k,int l,int r)
{
sum0[k]=sum1[k]=;
rev1[k]=rev2[k]=false;
if(l==r)
{
sum0[k]=big[dy[l]];
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
sum0[k]=sum0[k<<]+sum0[k<<|];
} void clear()
{
tot=cnt=;
memset(front,,sizeof(front));
memset(son,,sizeof(son));
memset(big,false,sizeof(big));
} int main()
{
freopen("data.in","r",stdin);
freopen("my.out","w",stdout);
int T;
read(T);
int u,v;
int ty,m,lca;
while(T--)
{
clear();
read(n);
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
dfs1();
dfs2(,);
build(,,n);
read(m);
while(m--)
{
read(ty); read(u); read(v);
solve(ty,u,v);
}
}
return ;
}
Little Devil I
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1087 Accepted Submission(s):
378
a devil. The devil always asks the king to do some crazy things. Although the
king used to be wise and beloved by his people. Now he is just like a boy in
love and can’t refuse any request from the devil. Also, this devil is looking
like a very cute Loli.
The devil likes to make thing in chaos. This
kingdom’s road system is like simply a tree(connected graph without cycle). A
road has a color of black or white. The devil often wants to make some change of
this system.
In details, we call a path on the tree from a to b consists
of vertices lie on the shortest simple path between a and b. And we say an edge
is on the path if both its two endpoints is in the path, and an edge is adjacent
to the path if exactly one endpoint of it is in the path.
Sometimes the
devil will ask you to reverse every edge’s color on a path or adjacent to a
path.
The king’s daughter, WJMZBMR, is also a cute loli, she is surprised
by her father’s lolicon-like behavior. As she is concerned about the
road-system’s status, sometimes she will ask you to tell there is how many black
edge on a path.
Initially, every edges is white.
number of the test cases.
For each test case, the first line contains an
integer n, which is the size of the tree. The vertices be indexed from 1.
On
the next n-1 lines, each line contains two integers a,b, denoting there is an
edge between a and b.
The next line contains an integer Q, denoting the
number of the operations.
On the next Q lines, each line contains three
integers t,a,b. t=1 means we reverse every edge’s color on path a to b. t=2
means we reverse every edge’s color adjacent to path a to b. t=3 means we query
about the number of black edge on path a to
b.
T<=5.
n,Q<=10^5.
Please use scanf,printf instead of
cin,cout,because of huge input.
line.
10
2 1
3 1
4 1
5 1
6 5
7 4
8 3
9 5
10 6
10
2 1 6
1 3 8
3 8 10
2 3 4
2 10 8
2 4 10
1 7 6
2 7 3
2 1 4
2 10 10
reverse color means change from white to black or vice virsa.
hdu 4857 Little Devil I的更多相关文章
- HDU 4857 拓扑排序 优先队列
n个数,已经有大小关系,现给m个约束,规定a在b之前,剩下的数要尽可能往前移.输出序列 大小关系显然使用拓扑结构,关键在于n个数本身就有大小关系,那么考虑反向建图,优先选择值最大的入度为零的点,这样得 ...
- HDU 4857
HDU 4857 (反向拓扑排序 + 优先队列) 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须 ...
- HDU 4857 topological_sort
逃生 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- codeforce E - Minimal Labels+hdu 4857
两个题目的意思差不多 都是希望得出的拓扑序如果有多种 要求输出字典序小的情况 这里引用一个大佬的博客 关于为什么不能直接建图然后用小根堆解决这个问题(http://blog.csdn.net/rgno ...
- HDU 4857 逃生 (反向拓扑排序 & 容器实现)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others) Mem ...
- HDU 4857 逃生 (优先队列+反向拓扑)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 解题报告:有n个点,有m个条件限制,限制是像这样的,输入a b,表示a必须排在b的前面,如果不 ...
- HDU 4897 Little Devil I(树链剖分)(2014 Multi-University Training Contest 4)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 Problem Description There is an old country and ...
- hdu 4857 逃生
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能 ...
- (hdu) 4857 逃生 (拓扑排序+优先队列)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄 ...
随机推荐
- MOSFET的小信号模型和频率响应
这部分内容大部分参考W.Y.Choi的课堂讲义第三讲和第四讲:http://tera.yonsei.ac.kr/class/2007_1/main.htm 一.小信号模型 首先要明确一点,大部分情形M ...
- 萌新程序媛的首个作品,基于NoSQL的内容管理及低码开发平台
尽管入行有一段时间了,但之前还从来没想过要开发一款完整的软件产品.这个我跟朋友开发的第一款软件,希望大家帮我们多宣传推广.首个版本肯定有很多的不足,大家也给我们多提意见,还有很多规划中的功能要在之后的 ...
- idea使用actiBPM插件中文乱码
idea 安转activiti插件后,编辑流程图发现保存后中文乱码,并且idea的字符集(Settings—>Editor—>File Encodings)已经设置为UTF-8,流程图中中 ...
- Bitmap 位图 Java实现
一.结构思想 以 bit 作为存储单位进行布尔值存取的数据结构. 表现为:给定第i位,该bit为1则表示true,为0则表示false. 二.使用场景及优点 适用于对布尔或0.1值进行(大量)存取的场 ...
- B1029 旧键盘 (20 分)
20/20,第一次没调试就过了. #include<bits/stdc++.h> using namespace std; /* 1.standardize 2.put to the se ...
- Go实现Pow工作量证明
之前使用python编写了一段代码实现了工作量证明机制,近期由于参与以太坊智能合约开发钱包的工作接触到golang语言,所以借此以go来实现Pow(Proof of work). 实现代码如下: // ...
- PAT甲题题解-1056. Mice and Rice (25)-模拟题
有n个老鼠,第一行给出n个老鼠的重量,第二行给出他们的顺序.1.每一轮分成若干组,每组m个老鼠,不能整除的多余的作为最后一组.2.每组重量最大的进入下一轮.让你给出每只老鼠最后的排名.很简单,用两个数 ...
- 全局最小割StoerWagner算法详解
前言 StoerWagner算法是一个找出无向图全局最小割的算法,本文需要读者有一定的图论基础. 本文大部分内容与词汇来自参考文献(英文,需***),用兴趣的可以去读一下文献. 概念 无向图的割:有无 ...
- 桌面输入法评测报告 之 搜狗拼音输入法vs必应拼音输入法
输入法是电脑用户不可或缺的软件,它几乎无时无刻不陪伴在使用者的身旁.一个优秀的输入法,应该满足客户对使用体验以及效率的需求.我们小队的任务便是对当今最为常用的两种输入法: 搜狗拼音输入法和必应拼音输入 ...
- 20135202闫佳歆--week4 两种方式使用同一个系统调用--实验及总结
实验四 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 在这里我选择的是第20号系统调用,getpid. 1.使用库函数API: 代码如下: /* getpid.c */ #incl ...