考试一共四个半小时,光这道题就打了三个小时。。然后又改了俩小时才过。我太蒟蒻了。

其实数据结构这种题就看第一遍打没打顺,顺了就A了,要是再找错再改就慢了,而且样例过了不能说明任何问题(虽然考试的时候我连样例都没出hhh)

给树按上三个新域,一个是左边的颜色,一个是右边的颜色,一个是颜色段数。
void pushup(int root)
{
     tree[root].lcol=tree[root<<1].lcol;
     tree[root].rcol=tree[root<<1|1].rcol;
     if(tree[root<<1].rcol==tree[root<<1|1].lcol)
       tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan-1;
     else
       tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan;
}

  

这段pushup想必大家就明白怎么递归了。

注意在往上爬的过程当中,一段一段中间的连接区域可能会有颜色相同,需要判断一下,找出fx。

完整代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define N 500000
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
int n,m;
int v[N];
struct haha
{
     int next,to;
}edge[N];
int head[N],cnt=1;
struct qian
{
  int left,right;
  int lcol,rcol,duan;
}tree[N];
int duan[N];
void add(int u,int v)
{
     edge[cnt].to=v;
     edge[cnt].next=head[u];
     head[u]=cnt++;
}
int rt[N];
int size[N],son[N],dep[N],fa[N];
void dfs1(int x)
{
    size[x]=1;son[x]=0;
    for(int i=head[x];i;i=edge[i].next)
    {
       int to=edge[i].to;
       if(to!=fa[x])
       {
          fa[to]=x;
          dep[to]=dep[x]+1;
          dfs1(to);
          size[x]+=size[to];
          if(size[to]>size[son[x]])
            son[x]=to;
       }
    }
}
int id[N],pos[N],top[N];
int ji;
void dfs2(int x,int tp)
{
     top[x]=tp;
     id[x]=++ji;
     pos[ji]=x;
     if(son[x])
       dfs2(son[x],tp);
     for(int i=head[x];i;i=edge[i].next)
     {
        int to=edge[i].to;
        if(to!=fa[x]&&to!=son[x])
          dfs2(to,to);
     }
}
void pushup(int root)
{
     tree[root].lcol=tree[root<<1].lcol;
     tree[root].rcol=tree[root<<1|1].rcol;
     if(tree[root<<1].rcol==tree[root<<1|1].lcol)
       tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan-1;
     else
       tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan;
}
void build(int left,int right,int root)
{
     rt[root]=-1;
     tree[root].left=left;
     tree[root].right=right;
     if(left==right)
     {
        tree[root].lcol=tree[root].rcol=v[pos[left]];
        tree[root].duan=1;
        return;
     }
     int mid=(left+right)>>1;
     build(left,mid,root<<1);
     build(mid+1,right,root<<1|1);
     pushup(root);
}
void pushdown(int root)
{
     if(rt[root]>=0)
     {
        rt[root<<1]=rt[root];
        rt[root<<1|1]=rt[root];
        tree[root<<1].lcol=tree[root<<1].rcol=rt[root];
        tree[root<<1|1].lcol=tree[root<<1|1].rcol=rt[root];
        tree[root<<1].duan=tree[root<<1|1].duan=1;
        rt[root]=-1;
     }
}
void change(int left,int right,int num,int root)
{
     if(left<=tree[root].left&&right>=tree[root].right)
     {
        rt[root]=num;
        tree[root].lcol=tree[root].rcol=num;
        tree[root].duan=1;
        return;
     }
     pushdown(root);
     int mid=(tree[root].right+tree[root].left)>>1;
     if(left<=mid)
       change(left,right,num,root<<1);
     if(right>mid)
       change(left,right,num,root<<1|1);
     pushup(root);
}
int query(int left,int right,int root)
{
    if(left<=tree[root].left&&right>=tree[root].right)
      return tree[root].duan;
    pushdown(root);
    int mid=(tree[root].left+tree[root].right)>>1;
    if(right<=mid)
       return query(left,right,root<<1);
    else
      if(left>mid)
         return query(left,right,root<<1|1);
      else
      {
          int tmp=1;
          if(tree[root<<1].rcol!=tree[root<<1|1].lcol)
            tmp=0;
          return query(left,mid,root<<1)+query(mid+1,right,root<<1|1)-tmp;
      }
}

int temp1,temp2;
void check(int po,int root)
{
    pushdown(root);
    if(tree[root].left==tree[root].right)
    {
       temp1=tree[root].lcol;
       return;
    }
    int mid=(tree[root].right+tree[root].left)>>1;
    if(po<=mid)
       check(po,root<<1);
    else
       check(po,root<<1|1);
}
void check2(int po,int root)
{
    pushdown(root);
    if(tree[root].left==tree[root].right)
    {
       temp2=tree[root].lcol;
       return;
    }
    int mid=(tree[root].right+tree[root].left)>>1;
    if(po<=mid)
       check2(po,root<<1);
    else
       check2(po,root<<1|1);
}

int erx,fux,ery,fuy;
int Query(int x,int y)
{
    int fx=top[x],fy=top[y];
    int ans=0;
    while(fx!=fy)
    {
       if(dep[fx]>dep[fy])
       {
           check(id[fa[fx]],1);
           check2(id[fx],1);
           ans+=query(id[fx],id[x],1);
           if(temp1==temp2)
             ans--;

           x=fa[fx];
           fux=x;
           erx=fx;
           fx=top[x];
       }
       else
       {
           check(id[fa[fy]],1);
           check2(id[fy],1);
           ans+=query(id[fy],id[y],1);
           if(temp1==temp2)
             ans--;

           y=fa[fy];
           fuy=y;
           ery=fy;
           fy=top[y];

       }

    }
    if(dep[x]>dep[y])
    {
      //check(id[erx],1);
      //check(id[fux],1);
      ans+=query(id[y],id[x],1);
      //if(temp1==temp2)
       //ans--;
    }
    else
    {
      //check(id[ery],1);
      //check(id[fuy],1);
      ans+=query(id[x],id[y],1);
      //if(temp1==temp2)
       //ans--;
    }
    return ans;
}
void Change(int x,int y,int z)
{
     int fx=top[x],fy=top[y];
     while(fx!=fy)
     {
        if(dep[fx]<dep[fy])
        {
          swap(fx,fy);
          swap(x,y);
        }
        change(id[fx],id[x],z,1);
        x=fa[fx];fx=top[x];
     }
     if(dep[x]>dep[y])
      swap(x,y);
     change(id[x],id[y],z,1);
}
int read()
{
    int su=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
       ch=getchar();
    while(ch<='9'&&ch>='0')
    {
                           su=su*10+ch-'0';
                           ch=getchar();
    }

    return su;
}
int main()
{
    //freopen("paint6.in","r",stdin);
    //freopen("paint66.out","w",stdout);
    scanf("%d%d",&n,&m);
    pos(i,1,n)
      v[i]=read();
    pos(i,1,n-1)
    {
       int x,y;
       x=read();y=read();
       add(x,y);
       add(y,x);
    }
    dfs1(1);
    dfs2(1,1);
    build(1,n,1);
    pos(i,1,m)
    {
       char p;
       int x,y,z;
       scanf("%s",&p);
       if(p=='C')
       {
          x=read();y=read();z=read();
          Change(x,y,z);
       }
       if(p=='Q')
       {
          x=read();y=read();
          printf("%d\n",Query(x,y));
       }
    }
    //while(1);
    return 0;
}

  

[SDOI2011]染色 线段树+树链剖分的更多相关文章

  1. bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 7925  Solved: 2975[Submit][Status ...

  2. 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分

    正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...

  3. [BZOJ2243][SDOI2011]染色 解题报告|树链剖分

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  4. [Bzoj2243][SDOI2011]染色(线段树&&树剖||LCT)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243 线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色 ...

  5. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  6. bzoj2243: [SDOI2011]染色--线段树+树链剖分

    此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...

  7. P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)

    #include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...

  8. P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)

    #include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...

  9. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

随机推荐

  1. js原生获取className&多选一

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. AngularJS服务和路由

    colnplie     网页加载的出现一次 link     元素每次改变的时候 **$watch** 监听列表     $scope.$watch("name",functio ...

  3. css 样式 设置图片成为圆形

    <div style="float: left;border-radius:70%; height: 80px; overflow:hidden;"> <img ...

  4. MOF编译器无法连接VMI服务器。原因可能是语义错误的解决方案

    安装数据库时报错. 我这个是因为安装SQL SERVER时,没有卸载vs. 一般解决方法: WIN 7安装VS和SQL SERVER的顺序应该是先安装SQL SERVER 然后安装VS,当要重装SQL ...

  5. Pandas数据处理实战:福布斯全球上市企业排行榜数据整理

    手头现在有一份福布斯2016年全球上市企业2000强排行榜的数据,但原始数据并不规范,需要处理后才能进一步使用. 本文通过实例操作来介绍用pandas进行数据整理. 照例先说下我的运行环境,如下: w ...

  6. javaSE 第77节课

    1.InetAddress InetAddress是地址的封装类,也可通过它来获得当前的操作地址(1)获得电脑当前上网的IP地址 (2)与服务器连接操作 (3) 二.MD5加密文件 文件本地秒传操作例 ...

  7. 第一课 1) 控制div属性 总结

    点击按钮变换属性: <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  8. zTree学习实例

    今天做完一个zTree的实例,供有需要的学习! 效果图如下:

  9. Jenkins2 实现持续交付初次演练(MultiJob,Pipeline,Blue Ocean)

    背景 项目需要用到自动部署,但可获取外网的节点机器只有一台,那只能同过主节点机器进行构建完成然后分发至对应服务器进行启动更新. 目前已尝试过三种方式: 1.Pipeline-Trigger param ...

  10. (转)Linux系统安装时分区的选择

    场景:对于Linux系统的分区总是迷迷茫茫的,还是实践少,基础不牢. 以前初识Linux时,对Linux系统安装时分区的选择,一点都不了解,导致几次没法进行下一步安装,因此就静下心来,专门拿出时间研究 ...