传送阵: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. 2016.5.27 php测试中敏感度高,怎么调整

    在测试PHP代码的过程中,会遇到这样的问题:PHP提示Notice: Undefined variable,遇到这样的问题很纠结,但是很容易解决. 今天晚上,我就遇到了这样的问题,到网上搜索了很多解决 ...

  2. 《DSP using MATLAB》示例Example4.14

    代码: b = [1]; a = [1, -1.5, 0.5]; % [R, p, C] = residuez(b,a) Mp = (abs(p))' Ap = (angle(p))'/pi % ch ...

  3. Java String类的常用方法

    String(byte[ ] bytes):通过byte数组构造字符串对象. String(char[ ] value):通过char数组构造字符串对象. String(Sting original) ...

  4. oracle sql别名

    为sql的字段起一个别名,常以为是可有可无的,但是有时候是必要的. 例如在ibatis中 <!-- 获取已发或待发送的彩信记录列表 --> <resultMap id="m ...

  5. NUC_TeamTEST_C && POJ2299(只有归并)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 42627   Accepted: 15507 ...

  6. Uva401Palindromes

      Palindromes  A regular palindrome is a string of numbers or letters that is the same forward as ba ...

  7. Codeforces Round #353 (Div. 2)Restoring Painting

    Vasya works as a watchman in the gallery. Unfortunately, one of the most expensive paintings was sto ...

  8. Codeforces Round #215 (Div. 2) C. Sereja and Algorithm

    #include <iostream> #include <vector> #include <algorithm> #include <string> ...

  9. webstorm常用快捷键(常用)

    ctrl+/ 注释 ctrl+shift+/ 注释一块的代码 ctrl+shift+z 返回撤撤销前的操作 ctrl+shift+up/down 代码向上/向下移动 ctrl+b或ctrl+鼠标左键单 ...

  10. 【BZOJ】2741: 【FOTILE模拟赛】L

    题意:给定一个长度为n的序列,m次询问,每次询问一个区间[l, r],求max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r.(n< ...