原文链接http://www.cnblogs.com/zhouzhendong/p/8081514.html


题目传送门 - BZOJ3862


题意概括

  一棵树,n个点,边权为黑或者白,支持3重操作:

  1.链上颜色翻转

  2.对于一条链,把有一个点在这条链上的边全部翻转颜色

  3.询问一条链上有多少黑色。


题解

  毒瘤题。

  对于1、3都是基础操作,很简单。

  主要是2.

  2的话,只需要打区间打标记,表示那些点的连向轻儿子的边全部翻转。然后修改的时候还有一堆特判(具体看代码)

  这题数据坑。

  有a==b的情况,小心了。我被坑了一个下午。

  我是怎么找到这个数据的呢?

  if (a==b) OLE();

void OLE(){
int a[100];
for (int i=23333;;i=i*i)
printf("233");
}

  


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
bool isd(char ch){return '0'<=ch&&ch<='9';}
int read(){
int x=0;
char ch=getchar();
while (!isd(ch))
ch=getchar();
while (isd(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=100005;
struct Gragh{
int cnt,y[N*2],nxt[N*2],fst[N];
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b){
y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
int T,n,q,cnp;
int size[N],fa[N],depth[N],son[N],p[N],ap[N],top[N];
void Get_Gen_Info(int rt,int pre,int d){
size[rt]=1,son[rt]=-1,fa[rt]=pre,depth[rt]=d;
for (int i=g.fst[rt];i;i=g.nxt[i])
if (g.y[i]!=pre){
int s=g.y[i];
Get_Gen_Info(s,rt,d+1);
size[rt]+=size[s];
if (son[rt]==-1||size[s]>size[son[rt]])
son[rt]=s;
}
}
void Get_Top(int rt,int tp){
top[rt]=tp;
ap[p[rt]=++cnp]=rt;
if (!~son[rt])
return;
Get_Top(son[rt],tp);
for (int i=g.fst[rt];i;i=g.nxt[i]){
int s=g.y[i];
if (s!=fa[rt]&&s!=son[rt])
Get_Top(s,s);
}
}
const int S=N*4;
struct Tree{
int sum,size,r,sr;
}t[S];
void build(int rt,int L,int R){
t[rt].size=R-L+1,t[rt].sum=t[rt].r=t[rt].sr=0;
if (L==R)
return;
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
build(ls,L,mid);
build(rs,mid+1,R);
}
void pushup(int rt){
int ls=rt<<1,rs=ls|1;
t[rt].sum=t[ls].sum+t[rs].sum;
}
void pushdown(int rt){
int ls=rt<<1,rs=ls|1;
int &sr=t[rt].sr,&r=t[rt].r;
if (sr)
t[ls].sr^=1,t[rs].sr^=1,sr=0;
if (r){
t[ls].r^=1,t[ls].sum=t[ls].size-t[ls].sum;
t[rs].r^=1,t[rs].sum=t[rs].size-t[rs].sum;
r=0;
}
}
void update(int rt,int L,int R,int xL,int xR,int op){
if (R<xL||L>xR)
return;
if (xL<=L&&R<=xR){
if (op==1){
t[rt].sum=t[rt].size-t[rt].sum;
t[rt].r^=1;
}
else
t[rt].sr^=1;
return;
}
pushdown(rt);
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
update(ls,L,mid,xL,xR,op);
update(rs,mid+1,R,xL,xR,op);
pushup(rt);
}
int query(int rt,int L,int R,int xL,int xR){
if (R<xL||L>xR)
return 0;
if (xL<=L&&R<=xR)
return t[rt].sum;
pushdown(rt);
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
return query(ls,L,mid,xL,xR)+query(rs,mid+1,R,xL,xR);
}
int asksr(int rt,int L,int R,int pos){
if (L==R)
return t[rt].sr;
pushdown(rt);
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
if (pos<=mid)
return asksr(ls,L,mid,pos);
else
return asksr(rs,mid+1,R,pos);
}
void Tupdate(int a,int b,int op){
if (a==b)
return;
int f1=top[a],f2=top[b];
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b);
update(1,1,n,p[f1],p[a],op);
if (op==2){
update(1,1,n,p[f1],p[f1],1);
if (~son[a])
update(1,1,n,p[son[a]],p[son[a]],1);
}
a=fa[f1],f1=top[a];
}
if (depth[a]>depth[b])
swap(a,b);
if (op==2){
update(1,1,n,p[a],p[b],2);
update(1,1,n,p[a],p[a],1);
if (~son[b])
update(1,1,n,p[son[b]],p[son[b]],1);
}
else if (a!=b)
update(1,1,n,p[son[a]],p[b],op);
}
int Tquery(int a,int b){
int f1=top[a],f2=top[b],ans=0;
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b);
if (f1!=a)
ans+=query(1,1,n,p[son[f1]],p[a]);
ans+=query(1,1,n,p[f1],p[f1])^asksr(1,1,n,p[fa[f1]]);
a=fa[f1],f1=top[a];
}
if (depth[a]>depth[b])
swap(a,b);
if (a!=b)
ans+=query(1,1,n,p[son[a]],p[b]);
return ans;
}
int main(){
T=read();
while (T--){
n=read();
g.clear();
for (int i=1,a,b;i<n;i++){
a=read(),b=read();
g.add(a,b),g.add(b,a);
}
cnp=0;
Get_Gen_Info(1,0,0);
Get_Top(1,1);
build(1,1,n);
q=read();
while (q--){
int op,a,b;
op=read(),a=read(),b=read();
if (a==b){
if (op==3)
puts("0");
if (op==2){
update(1,1,n,p[a],p[a],2);
if (~son[a])
update(1,1,n,p[son[a]],p[son[a]],1);
if (fa[a])
update(1,1,n,p[a],p[a],1);
}
continue;
}
if (op<3)
Tupdate(a,b,op);
if (op==3)
printf("%d\n",Tquery(a,b));
}
}
return 0;
}

  

BZOJ3862 Little Devil I 树链剖分的更多相关文章

  1. hdu_4897_Little Devil I(树链剖分)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 题意:有三种操作,1是在树上的两个节点之间的路径改变当前的颜色,2是改变树上有且只有一个端点在u ...

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

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

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

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

  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. Android App签名打包

    Andriod应用程序如果要在手机或模拟器上安装,必须要有签名!  1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序 ...

  2. python学习第39天

    # 数据操作 # 增 # 删 # 改 # 查 # 单表查询 # 多表查询

  3. Laravel 5.2数据库--填充数据

    1.简介 Laravel 包含了一个简单方法来填充数据库——使用填充类和测试数据.所有的填充类都位于database/seeds目录.填充类的类名完全由你自定义,但最好还是遵循一定的规则,比如可读性, ...

  4. Tornado学习笔记(二) 路由/post/get传参

    本章我们学习 Tornado 的路由传参等问题 路由 路由的匹配 Tornado的路由匹配采用的是正则匹配 一般情况下不需要多复杂的正则,正则的基本规则如下(站长之家) 举个例子 (r'/sum/(\ ...

  5. linux命令排序

    sort -k1 -n 第一列按数字正排序 sort -K1 -rn 第一列按数字倒排序

  6. Confluence 6 性能优化

    这个页面帮助你对应用性能进行提升需要进行的一些操作.这个页面不是为你对 Confluence 出现问题后进行问题修复的指南.如果你的 Confluence 崩溃的话,请查看Troubleshootin ...

  7. Confluence 6 禁用管理员联系表单

    如果你希望禁用这个功能,不允许用户通过发送电子邮件的方式联系站点管理员.你可以禁用这个页面中有关输入用户信息发送电子邮件的部分.你只能禁用用户电子邮件输入表单,如果你按照上面描述的步骤在 'Custo ...

  8. try? try! try do catch try 使用详解

    当一个使用一个方法发现后面 throws  说明可能会抛出异常 需要try 进行处理 1  try? 如果解析成功就有值 否则返回nil  (推荐) 2  try! 如果解析成功就有值  否则直接崩溃 ...

  9. Vue 导入文件import、路径@和.的区别

    ***import: html文件中,通过script标签引入js文件.而vue中,通过import xxx from xxx路径的方式导入文件,不光可以导入js文件. from前的:“xxx”指的是 ...

  10. SpringMvc框架MockMvc单元测试注解及其原理分析

    来源:https://www.yoodb.com/ 首先简单介绍一下Spring,它是一个轻量级开源框架,简单的来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开 ...