传送阵: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. zoj 3469 Food Delivery 区间dp + 提前计算费用

    Time Limit: 2 Seconds      Memory Limit: 65536 KB When we are focusing on solving problems, we usual ...

  2. 4、delphi record数组复制

    SetLength(OldDeptInfo,0); //释放旧数组 OldDeptInfo:=nil; 这样也可以: //SetLength(OldDeptInfo,Length(NewDeptInf ...

  3. 每天一个linux命令--su

    su命令和su -命令最大的本质区别就是:前者只是切换了root身份,但Shell环境仍然是普通用户的Shell:而后者连用户和Shell环境一起切换成root身份了. [richmail@porta ...

  4. WPF拖放功能实现zz

    写在前面:本文为即兴而作,因此难免有疏漏和词不达意的地方.在这里,非常期望您提供评论,分享您的想法和建议. 这是一篇介绍如何在WPF中实现拖放功能的短文. 首先要读者清楚的一件事情是:拖放主要分为拖放 ...

  5. HDU2191(多重背包)

    #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> ...

  6. 【BZOJ】2938: [Poi2000]病毒

    题意 \(n\)个01病毒串,总长不超过\(30000\).问是否存在无限长的不包含病毒串的01串. 分析 考虑ac自动机,如果不包含病毒串而且无限长也就是说存在一个环(转移和fail树),使得环上不 ...

  7. SRM 594 DIV1 250

    可能开始宿舍比较乱,思绪静不下来...想了大半个小时,终于确定了应该暴力+DP,然后写了枚举除数,和被除的版本..这样,还敲错了个字母,第一次提交还100多,修改提交还有75.多,最后想到,貌似不打对 ...

  8. LVS DR脚本 解析

    vip.sh #!/bin/bash 192.168.2.240 broadcast 192.168.2.240 netmask 255.255.255.255 up route add -host ...

  9. WinForm上显示gif动画:转

    WinForm上的ProgressBar,老实说,实在是不敢恭维,太死板,太难看了,即使做成实时显示处理进度的,它还是逃离不了“难看”.现 在的web2.0上到处都能看到一个显示正在处理的小圆圈在那转 ...

  10. .net的五层架构

    原文章地址是http://www.360doc.com/content/11/1210/21/19147_171335782.shtml 我们刚开始学习架构的时候,首先会想到分层的概念,分层架构比较经 ...