传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4897

题目大意:一棵树,三个操作:1、将某条链取反,2、将与某条链相邻的边取反,3、查询某条链上为1的边数

树链剖分直接上

某条边是否被修改取决于这条边以及这条边的两个端点

对于第一个操作相当于修改边,第二个操作相当于修改点

对于修改边:将标记下放给儿子结点,直接修改即可,修改点也是直接修改,不过要另设一个标记记录

查询时将所有区间合并即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define maxn 100010
using namespace std;
inline int read(){
int s=;char ch=getchar();
for(;ch<''||ch>'';ch=getchar());
for(;ch>=''&&ch<='';ch=getchar())s=s*+ch-'';
return s;
}
int fa[maxn][],dep[maxn],f[maxn];
int to[maxn<<],Next[maxn<<],tot,h[maxn];
int pos[maxn],sz,size[maxn];
struct node{
int lb,ld,rd,w,s,md,mb;
void clear(){
lb=ld=rd=w=s=mb=md=;
}
friend node operator + (node a,node b){
node ans;
ans.s=a.s+b.s+;
ans.w=a.w+b.w+(a.rd^b.lb^b.ld);
ans.ld=a.ld;
ans.lb=a.lb;
ans.rd=b.rd;
return ans;
}
}t[maxn<<];
int n,q;
void mem(){
tot=;sz=;
memset(h,,sizeof(h));
memset(fa,,sizeof(fa));
memset(dep,,sizeof(dep));
memset(f,,sizeof(f));
memset(pos,,sizeof(pos));
memset(size,,sizeof(size));
memset(t,,sizeof(t));
}
void add(int x,int y){
tot++;to[tot]=y;Next[tot]=h[x];h[x]=tot;
}
void dfs(int x){
for(int i=;i<=;++i)
if(dep[x]<(<<i))break;
else fa[x][i]=fa[fa[x][i-]][i-];
for(int i=h[x];i;i=Next[i]){
int v=to[i];
if(dep[v])continue;
fa[v][]=x;
dep[v]=dep[x]+;
dfs(v);
size[x]+=size[v];
}size[x]++;
}
void dfs(int x,int ff){
pos[x]=++sz;f[x]=ff;int mx=;
for(int i=h[x];i;i=Next[i])
if(dep[to[i]]>dep[x]&&size[to[i]]>size[mx])
mx=to[i];
if(!mx)return;
dfs(mx,ff);
for(int i=h[x];i;i=Next[i])
if(dep[to[i]]>dep[x]&&mx!=to[i])
dfs(to[i],to[i]);
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int d=dep[x]-dep[y];
for(int i=;i<=;++i)
if(d&(<<i))
x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;--i)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if(x==y)return x;
return fa[x][];
}
#define L(k) (k<<1)
#define R(k) (k<<1|1)
void pushdown(int k){
if(t[k].md){
t[L(k)].md^=;t[R(k)].md^=;
t[L(k)].ld^=;t[R(k)].ld^=;
t[L(k)].rd^=;t[R(k)].rd^=;
t[k].md=;
}
if(t[k].mb){
t[L(k)].mb^=;t[R(k)].mb^=;
t[L(k)].w=t[L(k)].s-t[L(k)].w;
t[R(k)].w=t[R(k)].s-t[R(k)].w;
t[L(k)].lb^=;t[R(k)].lb^=;
t[k].mb=;
}
}
void update(int k){
node a=t[k];
t[k]=t[L(k)]+t[R(k)];
t[k].mb=a.mb;
t[k].md=a.md;
}
void build(int k,int l,int r){
if(l==r)return;
int mid=(l+r)>>;
build(L(k),l,mid);
build(R(k),mid+,r);
update(k);
}
void change1(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){
t[k].mb^=;
t[k].w=t[k].s-t[k].w;
t[k].lb^=;
return;
}
pushdown(k);
int mid=(l+r)>>;
if(x<=mid)change1(L(k),l,mid,x,y);
if(y>mid)change1(R(k),mid+,r,x,y);
update(k);
}
void work1(int x,int y){
int k=lca(x,y);
while(f[x]!=f[k]){
change1(,,n,pos[f[x]],pos[x]);x=fa[f[x]][];
}if(x!=k)change1(,,n,pos[k]+,pos[x]);
while(f[y]!=f[k]){
change1(,,n,pos[f[y]],pos[y]);y=fa[f[y]][];
}if(y!=k)change1(,,n,pos[k]+,pos[y]);
}
void change2(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){
t[k].md^=;
t[k].ld^=;
t[k].rd^=;
return;
}
pushdown(k);
int mid=(l+r)>>;
if(x<=mid)change2(L(k),l,mid,x,y);
if(y>mid)change2(R(k),mid+,r,x,y);
update(k);
}
void work2(int x,int y){
int k=lca(x,y);
while(f[x]!=f[k]){
change2(,,n,pos[f[x]],pos[x]);x=fa[f[x]][];
}if(x!=k)change2(,,n,pos[k]+,pos[x]);
while(f[y]!=f[k]){
change2(,,n,pos[f[y]],pos[y]);y=fa[f[y]][];
}change2(,,n,pos[k],pos[y]);
}
node ask(int k,int l,int r,int x,int y){
if(x<=l&&r<=y)return t[k];
pushdown(k);
int mid=(l+r)>>;
node ans;ans.clear();int flag=;
if(x<=mid)ans=ask(L(k),l,mid,x,y),flag=;
if(y>mid){
if(flag)ans=ans+ask(R(k),mid+,r,x,y);
else ans=ask(R(k),mid+,r,x,y);
}
update(k);
return ans;
}
int ask(int k,int l,int r,int x){
if(l==r)return t[k].ld;
pushdown(k);
int mid=(l+r)>>;
int ans;
if(x<=mid)ans=ask(L(k),l,mid,x);
else ans=ask(R(k),mid+,r,x);
update(k);
return ans;
}
node work3(int k,int x){
node ans;ans.clear();
int flag=;
while(f[x]!=f[k]){
if(flag)ans=ask(,,n,pos[f[x]],pos[x])+ans;
else ans=ask(,,n,pos[f[x]],pos[x]);
flag=;x=fa[f[x]][];
}
if(x!=k){
if(flag)ans=ask(,,n,pos[k]+,pos[x])+ans;
else ans=ask(,,n,pos[k]+,pos[x]);
}
return ans;
}
void getans(int x,int y){
int k=lca(x,y);
node L=work3(k,x);
node R=work3(k,y);
int tmp=ask(,,sz,pos[k]);
int ans=L.w+R.w;
if(x!=k)ans+=(L.lb^L.ld^tmp);
if(y!=k)ans+=(R.lb^R.ld^tmp);
printf("%d\n",ans);
}
int main(){
int T;scanf("%d",&T);
while(T--){
mem();
n=read();
for(int i=;i<n;++i){
int a=read(),b=read();
add(a,b);add(b,a);
}
dep[]=;dfs();
dfs(,);
build(,,sz);
q=read();
for(int i=;i<=q;++i){
int opt=read(),a=read(),b=read();
if(opt==)work1(a,b);
if(opt==)work2(a,b);
if(opt==)getans(a,b);
}
}
return ;
}

hdu 4897 Little Devil I的更多相关文章

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

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

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

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

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

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

  5. hdu 4857 Little Devil I

    http://acm.hdu.edu.cn/showproblem.php?pid=4897 题意:给你一棵树,边的颜色要么为白色,要么为黑色,初始每条边为白色,有三种操作 1.将u-v链上面的所有边 ...

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

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

  7. hdu 4899 Hero meet devil

    传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4899 题目大意:给定一个DNA序列,求有多少长度为m的序列与该序列的最长公共子序列长度为0,1...|S ...

  8. HDU 4899 Hero meet devil(状压DP)(2014 Multi-University Training Contest 4)

    Problem Description There is an old country and the king fell in love with a devil. The devil always ...

  9. HDU 4899 Hero meet devil (状压DP, DP预处理)

    题意:给你一个基因序列s(只有A,T,C,G四个字符,假设长度为n),问长度为m的基因序列s1中与给定的基因序列LCS是0,1......n的有多少个? 思路:最直接的方法是暴力枚举长度为m的串,然后 ...

随机推荐

  1. JDK BIO编程

    网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建 ...

  2. Xamarin基础命名空间Microsoft.SqlServer.Server

    Xamarin基础命名空间Microsoft.SqlServer.Server   该命名空间包含大量的类.接口和枚举,用于操作微软SQL Server数据库.该空间支持Xamarin.iOS和Xam ...

  3. Python int与string 的转换

    string → int 1.10进制的string转化为int int('12')  → type(int('12')) 进行验证 2.16进制的string转化为int int('12', 16) ...

  4. Monkeyrunner脚本中component快速定位方法

    在编写MonkeyRunner脚本过程中,会出现component这一项内容,很多人可能不知道怎么确认,其实这个主要是为了指定要测试的程序包名和主Activity名,我们可以用以下方法去进行确认: 1 ...

  5. Redis入门指南

    随着互联网业务对性能需求日益强烈,作为Key/Value存储的Redis具有数据类型丰富和性能表现优异的特点.如果能够熟练地驾驭它,不管是把它用做缓存还是存储,对很多大型应用都很多帮助.新浪作为世界上 ...

  6. ural 2070. Interesting Numbers

    2070. Interesting Numbers Time limit: 2.0 secondMemory limit: 64 MB Nikolay and Asya investigate int ...

  7. The Parallel Challenge Ballgame[HDU1101]

    The Parallel Challenge Ballgame Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ( ...

  8. 20145308刘昊阳 《Java程序设计》第4周学习总结

    20145308刘昊阳 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承与多态 6.1 何谓继承 继承:面向对象中,为避免多个类间重复定义共同行为使用 把相同代码提升为父 ...

  9. scrollIntoView

    DOM的滚动 DOM规范中并没有规定各浏览器需要实现怎样的滚动页面区域,各浏览器实现了相应的方法,可以使用不同的方式控制页面区域的滚动.这些方法作为HTMLElement类型的扩展存在,所以它能在所有 ...

  10. JS中的专业术语

    本身虽然是学技术出身,但.....此处省略N个字符 1.Namespace 命名空间 允许开发人员在一个独特, 应用相关的名字的名称下捆绑所有功能的容器. 2.Class类 定义对象的特征.它是对象的 ...