当前位置: 首页 > news >正文

hdu 4857 Little Devil I

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

 

题意:
给你一棵树,边的颜色要么为白色,要么为黑色,初始每条边为白色,有三种操作

1、将u-v链上面的所有边的颜色翻转
2、将u-v链上面所有邻接的边翻转(边上只有一个点在链上面)
3、询问u->v上面有多少黑色的边

 

树链剖分,线段树维护4个信息:

按dfs序建立线段树后,如果线段树内节点的区间为[l,r],则此节点维护树上dfs序[l,r]内的父边的信息

父边指 点与父节点之间的边

sum0:节点的父边属于重链且颜色为白色 的边数

sum1:节点的父边属于重链且颜色为黑色 的边数

rev1:节点的父边颜色是否被操作1取反 (实际只会用到属于轻链的边)

rev2:节点的子树中,与节点直接相连的属于轻链边 是否被操作2取反

 

操作1:直接取反,交换sum0和sum1,维护标记rev1

细节:最后u和v(dep[u]<dep[v])汇集到一条重链的时候,最后一次操作不包括u,因为点代表的是父边的信息

 

操作2:一条链的相邻边,除了对链上的点维护rev2操作外,

链最顶端的点如果是其父节点的重儿子,需要修改它的rev1

路径上每条重链最底端的点,如果它有重儿子,需要修改它重儿子的rev1

因为标记rev2只维护轻链

 

操作3:重链直接查,轻链呢?

在树链剖分往上跳的时候,跳轻链一定是只跳一条边

假设这条边连接了节点u和v,dep[u]<dep[v]

如果rev2[u]^rev2[v]^rev1[v] 为 true,则这条边为黑色

 

clj的题就是好哇!!!

 

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

using namespace std;

#define N 100001

int n;

int front[N],nxt[N<<1],to[N<<1],tot;

int siz[N],dep[N],fa[N];
int bl[N],son[N];
int id[N],dy[N],cnt;

bool big[N];

int sum0[N<<2],sum1[N<<2];
bool rev1[N<<2],rev2[N<<2];

int ans;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void add(int u,int v)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}

void dfs1(int x)
{
    siz[x]=1;
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=fa[x])
        {
            fa[to[i]]=x;
            dep[to[i]]=dep[x]+1;
            dfs1(to[i]);
            siz[x]+=siz[to[i]];
        }
}

void dfs2(int x,int top)
{
    bl[x]=top;
    id[x]=++cnt;
    dy[cnt]=x;
    int y=0;
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=fa[x] && siz[to[i]]>siz[y]) y=to[i];
    if(y) 
    {
        son[x]=y;
        big[y]=true;
        dfs2(y,top);
    }
    else return;
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=fa[x] && to[i]!=y) dfs2(to[i],to[i]);
}

void down1(int k)
{
    rev1[k<<1]^=1;
    swap(sum0[k<<1],sum1[k<<1]);
    rev1[k<<1|1]^=1;
    swap(sum0[k<<1|1],sum1[k<<1|1]);
    rev1[k]^=1;
}

void down2(int k)
{
    rev2[k<<1]^=1;
    rev2[k<<1|1]^=1;
    rev2[k]^=1;
}

void Reverse(int k,int l,int r,int opl,int opr,int ty)
{
    if(l>=opl && r<=opr)
    {
        if(ty==1)
        {
            swap(sum1[k],sum0[k]);
            rev1[k]^=1;
        }
        else rev2[k]^=1;
        return;
    }
    int mid=l+r>>1;
    if(rev1[k]) down1(k);
    if(rev2[k]) down2(k);
    if(opl<=mid) Reverse(k<<1,l,mid,opl,opr,ty);
    if(opr>mid) Reverse(k<<1|1,mid+1,r,opl,opr,ty);
    if(ty==1)
    {
        sum1[k]=sum1[k<<1]+sum1[k<<1|1];
        sum0[k]=sum0[k<<1]+sum0[k<<1|1];
    }
}

int get_lca(int u,int v)
{
    while(bl[u]!=bl[v])
    {
        if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
        u=fa[bl[u]];
    }
    return dep[u]<dep[v] ? u : v;
}

bool point_query(int k,int l,int r,int x,int ty)
{
    if(l==r) return ty==1 ? rev1[k] : rev2[k];
    if(rev1[k]) down1(k);
    if(rev2[k]) down2(k);
    int mid=l+r>>1;
    if(x<=mid) return point_query(k<<1,l,mid,x,ty);
    return point_query(k<<1|1,mid+1,r,x,ty);
}

void query(int k,int l,int r,int opl,int opr)
{
    if(l>=opl && r<=opr)
    {
        ans+=sum1[k];
        return;
    }
    if(rev1[k]) down1(k);
    if(rev2[k]) down2(k);
    int mid=l+r>>1;
    if(opl<=mid) query(k<<1,l,mid,opl,opr);
    if(opr>mid) query(k<<1|1,mid+1,r,opl,opr);
}

void solve(int ty,int u,int v)
{
    if(ty==1)
    {
        while(bl[u]!=bl[v])
        {
            if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
            Reverse(1,1,n,id[bl[u]],id[u],1);
            u=fa[bl[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        if(u!=v) Reverse(1,1,n,id[u]+1,id[v],1);
    }
    else if(ty==2)
    {
        int lca=get_lca(u,v);
        if(lca!=u && lca!=v) 
        {
            if(big[lca]) Reverse(1,1,n,id[lca],id[lca],1);
        }
        else
        {
            if(dep[u]>dep[v]) swap(u,v);
            if(big[u]) Reverse(1,1,n,id[u],id[u],1);
        }
        while(bl[u]!=bl[v])
        {
            if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
            if(son[u]) Reverse(1,1,n,id[son[u]],id[son[u]],1);
            Reverse(1,1,n,id[bl[u]],id[u],2);
            u=fa[bl[u]];
        }
        if(dep[u]>dep[v]) swap(u,v); 
        if(son[v]) Reverse(1,1,n,id[son[v]],id[son[v]],1);
        Reverse(1,1,n,id[u],id[v],2);
    }
    else
    {    
        ans=0;        
        while(bl[u]!=bl[v])
        {
            if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
            query(1,1,n,id[bl[u]],id[u]);
            ans+=point_query(1,1,n,id[bl[u]],2)^point_query(1,1,n,id[fa[bl[u]]],2)^point_query(1,1,n,id[bl[u]],1);
            u=fa[bl[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        if(u!=v) query(1,1,n,id[u]+1,id[v]);
        printf("%d\n",ans);
    }
}    

void build(int k,int l,int r)
{
    sum0[k]=sum1[k]=0;
    rev1[k]=rev2[k]=false;
    if(l==r) 
    {
        sum0[k]=big[dy[l]];
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    sum0[k]=sum0[k<<1]+sum0[k<<1|1];
}

void clear()
{
    tot=cnt=0;
    memset(front,0,sizeof(front));
    memset(son,0,sizeof(son));
    memset(big,false,sizeof(big));
}

int main()
{
    freopen("data.in","r",stdin);
    freopen("my.out","w",stdout);
    int T;
    read(T);
    int u,v;
    int ty,m,lca;
    while(T--)
    {
        clear();
        read(n);
        for(int i=1;i<n;++i)
        {
            read(u); read(v);
            add(u,v);
        }
        dfs1(1);
        dfs2(1,1);
        build(1,1,n);
        read(m);
        while(m--)
        {
            read(ty); read(u); read(v);
            solve(ty,u,v);
        }
    }
    return 0;
}

 

Little Devil I

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1087    Accepted Submission(s): 378


Problem Description
There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli.

The devil likes to make thing in chaos. This kingdom’s road system is like simply a tree(connected graph without cycle). A road has a color of black or white. The devil often wants to make some change of this system.

In details, we call a path on the tree from a to b consists of vertices lie on the shortest simple path between a and b. And we say an edge is on the path if both its two endpoints is in the path, and an edge is adjacent to the path if exactly one endpoint of it is in the path.

Sometimes the devil will ask you to reverse every edge’s color on a path or adjacent to a path.

The king’s daughter, WJMZBMR, is also a cute loli, she is surprised by her father’s lolicon-like behavior. As she is concerned about the road-system’s status, sometimes she will ask you to tell there is how many black edge on a path.

Initially, every edges is white.
 

 

Input
The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains an integer n, which is the size of the tree. The vertices be indexed from 1.
On the next n-1 lines, each line contains two integers a,b, denoting there is an edge between a and b.
The next line contains an integer Q, denoting the number of the operations.
On the next Q lines, each line contains three integers t,a,b. t=1 means we reverse every edge’s color on path a to b. t=2 means we reverse every edge’s color adjacent to path a to b. t=3 means we query about the number of black edge on path a to b.

T<=5.
n,Q<=10^5.
Please use scanf,printf instead of cin,cout,because of huge input.
 

 

Output
For each t=3 operation, output the answer in one line.
 

 

Sample Input
1 10 2 1 3 1 4 1 5 1 6 5 7 4 8 3 9 5 10 6 10 2 1 6 1 3 8 3 8 10 2 3 4 2 10 8 2 4 10 1 7 6 2 7 3 2 1 4 2 10 10
 

 

Sample Output
3
Hint
reverse color means change from white to black or vice virsa.
 

 

Author
WJMZBMR

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/8456845.html

相关文章:

  • Spring Boot实践--项目打包、启动、关闭的方法
  • centos7 安装 gitolite (git服务器)
  • 项目去掉svn管理标志
  • SSM-MyBatis-09:Mybatis中SqlSession的close为什么能造成事务的回滚
  • Javascript理解this对象
  • GNUPG
  • 零基础Python爬虫实现(百度贴吧)
  • 我对CopyOnWrite的思考
  • RabbitMQ入门-路由-有选择的接受消息
  • 报告称国产智能手机全球市场份额33.1% 超过韩国
  • iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
  • 深入理解java虚拟机 精华总结(面试)
  • Spring框架
  • DTS-071007 表结构在源库和目标库中不一致
  • 算法学习之路|聪明的打字员
  • php的引用
  • [case10]使用RSQL实现端到端的动态查询
  • 《深入 React 技术栈》
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • emacs初体验
  • iOS小技巧之UIImagePickerController实现头像选择
  • JavaScript对象详解
  • JS+CSS实现数字滚动
  • k8s 面向应用开发者的基础命令
  • k8s如何管理Pod
  • Making An Indicator With Pure CSS
  • Python十分钟制作属于你自己的个性logo
  • 缓存与缓冲
  • 目录与文件属性:编写ls
  • 强力优化Rancher k8s中国区的使用体验
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 深度学习中的信息论知识详解
  • 算法---两个栈实现一个队列
  • 我的面试准备过程--容器(更新中)
  • 小程序开发中的那些坑
  • 异步
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​LeetCode解法汇总518. 零钱兑换 II
  • #{} 和 ${}区别
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (42)STM32——LCD显示屏实验笔记
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (八)Spring源码解析:Spring MVC
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (学习日记)2024.01.19
  • (一)appium-desktop定位元素原理
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转)VC++中ondraw在什么时候调用的
  • ***监测系统的构建(chkrootkit )
  • .NET Core引入性能分析引导优化
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .Net 代码性能 - (1)
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化