题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4897

题意:有三种操作,1是在树上的两个节点之间的路径改变当前的颜色,2是改变树上有且只有一个端点在u,v之间的边的颜色,3是询问u,v之间黑色边的条数

题解:对于1,就是一般的树链剖分操作,对于2,我们知道树剖把树分成了重链和轻链,我们要充分利用这个结构才能降低时间复杂度,这里我们建立两个线段树来保存重链的sum和对每一个点的标记vis,第二个线段树表示如果这个点标记为1,那么以这个点周围的边都会改变,然后对于重链上的点,我们就直接在sum上操作,遇到轻链上的点,就在vis上标记,最后查询的时候先找sum上真实改变的边,然后当 当前的top跳到另一个top时,此时要查询vis上和sum上异或的值,最后全部加起来就是答案,要好好的想一想才能理解

 #include<cstdio>
#define F(i,a,b) for(int i=a;i<=b;i++) const int N=1e5+;
int t,n,op,q,x,y,g[N],nxt[N<<],v[N<<],ed;
inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
//--------------树链剖分---------------
int dep[N],sz[N],hs[N],top[N],fa[N],tid[N],idx;
void dfs1(int u,int pre){
fa[u]=pre,sz[u]=,dep[u]=dep[pre]+,hs[u]=;
for(int i=g[u];~i;i=nxt[i])if(v[i]!=pre)
dfs1(v[i],u),sz[u]+=sz[v[i]],hs[u]=sz[v[i]]>sz[hs[u]]?v[i]:hs[u];
}
void dfs2(int u,int tp){
tid[u]=++idx,top[u]=tp;
if(hs[u])dfs2(hs[u],tp);
for(int i=g[u];~i;i=nxt[i])
if(v[i]!=fa[u]&&v[i]!=hs[u])dfs2(v[i],v[i]);
}
//--------------线段树------------------
#define root 1,n,1
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
int sum[N<<],vis[N<<],ly1[N<<]; inline void sink(int rt,int tot){ly1[rt]^=,sum[rt]=tot-sum[rt];} inline void pd(int op,int l,int r,int rt){
if(op==){
if(ly1[rt]){
int m=(l+r)>>;
sink(rt<<,m-l+),sink(rt<<|,r-m);
ly1[rt]=;
}
}else if(vis[rt])vis[rt<<]^=,vis[rt<<|]^=,vis[rt]=;
}
inline void up_p(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
sink(rt,r+-l);
return;
}
pd(,l,r,rt);
int m=(l+r)>>;
if(L<=m)up_p(L,R,ls);
if(R>m)up_p(L,R,rs);
sum[rt]=sum[rt<<]+sum[rt<<|];
}
inline int q_p(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R)return sum[rt];
int m=(l+r)>>,ret=;
pd(,l,r,rt);
if(L<=m)ret+=q_p(L,R,ls);
if(m<R)ret+=q_p(L,R,rs);
return ret;
}
inline void up_v(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){vis[rt]^=;return;}
pd(,l,r,rt);
int m=(l+r)>>;
if(L<=m)up_v(L,R,ls);
if(R>m)up_v(L,R,rs);
}
inline int q_v(int x,int l,int r,int rt){
if(l==r)return vis[rt];
pd(,l,r,rt);
int m=(l+r)>>,ret=;
if(x<=m)ret^=q_v(x,ls);
else ret^=q_v(x,rs);
return ret;
}
//--------------------------------------
inline int ask(int x,int y){
int ans=;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
if(x!=top[x])ans+=q_p(tid[top[x]]+,tid[x],root);
ans+=q_v(tid[fa[top[x]]],root)^q_p(tid[top[x]],tid[top[x]],root);
x=fa[top[x]];
}
if(x==y)return ans;
if(dep[x]>dep[y])x^=y,y^=x,x^=y;
ans+=q_p(tid[x]+,tid[y],root);
return ans;
}
inline void up(int op,int x,int y){
if(op==){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
up_p(tid[top[x]],tid[x],root),x=fa[top[x]];
}
if(x!=y){
if(dep[x]>dep[y])x^=y,y^=x,x^=y;
up_p(tid[x]+,tid[y],root);
}
}else{
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
up_v(tid[top[x]],tid[x],root);
up_p(tid[top[x]],tid[top[x]],root);
if(hs[x])up_p(tid[x]+,tid[hs[x]],root);
x=fa[top[x]];
}
if(dep[x]>dep[y])x^=y,y^=x,x^=y;
up_v(tid[x],tid[y],root);
up_p(tid[x],tid[x],root);
if(hs[y])up_p(tid[y]+,tid[hs[y]],root);
}
} int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
F(i,,n)g[i]=-;ed=;
F(i,,n<<)sum[i]=,vis[i]=,ly1[i]=;
F(i,,n-)scanf("%d%d",&x,&y),adg(x,y),adg(y,x);
dfs1(,),idx=,dfs2(,),scanf("%d",&q);
while(q--){
scanf("%d%d%d",&op,&x,&y);
if(op<)up(op,x,y);else printf("%d\n",ask(x,y));
}
}
return ;
}

hdu_4897_Little Devil I(树链剖分)的更多相关文章

  1. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  2. hdu 4897 Little Devil I (树链剖分+线段树)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4897 题意: 给你一棵树,一开始每条边都是白色,有三种操作: 1.将 u - v路径上的边转换颜色 ...

  3. BZOJ3862 Little Devil I 树链剖分

    原文链接http://www.cnblogs.com/zhouzhendong/p/8081514.html 题目传送门 - BZOJ3862 题意概括 一棵树,n个点,边权为黑或者白,支持3重操作: ...

  4. HDU 4897 Little Devil I 树链剖分+线段树

    Little Devil I Problem Description There is an old country and the king fell in love with a devil. T ...

  5. 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 ...

  6. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  7. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  8. hdu 4897 树链剖分(重轻链)

    Little Devil I Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  9. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

随机推荐

  1. iOS学习笔记(01) - 泛型

    决定新开一坑,在不断学习的同时分享自己的学习历程给大家,既是对自己学习的记录,又希望能对大家提供些微的帮助. 这一篇文章主要来介绍泛型的意义.使用与声明方法等. 1.泛型:限制类型 1.1.泛型使用场 ...

  2. Compile Time Assertion..

    The most seen assertion are during runtime, but this one is at compile time, to give the error more ...

  3. IOS 导出ipa文件方法

    1.首先打开项目,Device选项栏选择“Generic iOS Device”.如下图所示: 2.选择屏幕上方的“product”并点击打开,选择“Archive”并点击打开,程序就会自动运行,运行 ...

  4. 用shell获得hadoop中mapreduce任务运行结果的状态

    在近期的工作中,我需要用脚本来运行mapreduce,并且要判断运行的结果,根据结果来做下一步的动作. 开始我想到shell中获得上一条命令运行结果的方法,即判断"$?"的值 if ...

  5. hadoop三个配置文件的参数含义说明core-site.xml,hdfs-site.xml,mapred-site.xml

    配置hadoop,主要是配置core-site.xml,hdfs-site.xml,mapred-site.xml三个配置文件,默认下来,这些配置文件都是空的,所以很难知道这些配置文件有哪些配置可以生 ...

  6. crossdomain 可用

    <cross-domain-policy> <allow-access-from domain="*"/> <allow-http-request-h ...

  7. php 获取地址栏参数

    javascript实现: top.location.href 顶级窗口的地址this.location.href 当前窗口的地址 PHP实现: //获取域名或主机地址 echo $_SERVER[' ...

  8. KMP算法中的next数组求解示意图

  9. 注意题目条件!!! 团问题 HDU 5952

    题目大意:团的定义就是,团内的所有点,两两之间各有一条边,团的大小就是点的个数.现给你一个n个点,m条边的图.问,该图中有多少点的个数为s的团. (题目保证每个点的度数不超过20,n<=100, ...

  10. php 特定类型测试函数

    is_array() 检查变量是否是数组 is_double().is_float().is_real() 检查变量是否是浮点数 is_long().is_int().is_integer()检查变量 ...