• bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)


    【bzoj2243】[SDOI2011]染色

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:

    1、将节点a到节点b路径上所有点都染成颜色c;

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数n和m,分别表示节点数和操作数;

    第二行包含n个正整数表示n个节点的初始颜色

    下面 行每行包含两个整数x和y,表示xy之间有一条无向边。

    下面 行每行描述一个操作:

    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

    Output

    对于每个询问操作,输出一行答案。

    Sample Input

    6 5
    2 2 1 2 1 1
    1 2
    1 3
    2 4
    2 5
    2 6
    Q 3 5
    C 2 1 1
    Q 3 5
    C 5 1 2
    Q 3 5

    Sample Output

    3
    1
    2

    HINT

    数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。、

    题解:

    题目很好理解,它不是边染色,而是点染色,这个性质是比较好的,边染色还需要裂点。

    看的题目就可以想到这是树链剖分模板题吧,套个裸的线段树合并,其实没有什么合并的

    东西,发现一段线段的不同颜色,那么就需要记录左端点和右端点颜色,如果左区间右端

    点和右区间左端颜色一样,那么总颜色-1,这个比较好理解的吧,然后记录一个该区间总

    颜色数,就可以统计了。

    程序比较结构化
    两个dfs预处理,lca,线段树,询问处理+更新处理,就ok了,代码比较清晰。

      1 #include<cstring>
      2 #include<cmath>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<cstdio>
      6 #include<cstdlib>
      7 #define N 100007
      8 using namespace std;
      9 
     10 int n,m,sz=0;
     11 int cnt,head[N],next[N*2],rea[N*2];
     12 int a[N];
     13 int fa[N][20],size[N],pos[N],bel[N],deep[N];
     14 char ch[2];
     15 struct Node
     16 {
     17     int lc,rc,tag,num;
     18 }tr[N*5];
     19 
     20 void add(int u,int v){next[++cnt]=head[u],head[u]=cnt,rea[cnt]=v;}
     21 void dfs_init(int u)
     22 {
     23     size[u]=1;
     24     for (int i=1;(1<<i)<=deep[u];i++)
     25         fa[u][i]=fa[fa[u][i-1]][i-1];
     26     for (int i=head[u];i!=-1;i=next[i])
     27     {
     28         int v=rea[i];
     29         if (v==fa[u][0]) continue;
     30         deep[v]=deep[u]+1;
     31         fa[v][0]=u;
     32         dfs_init(v);
     33         size[u]+=size[v];
     34     }
     35 }
     36 void dfs_make(int u,int chain)
     37 {
     38     int k=0;
     39     pos[u]=++sz,bel[u]=chain;
     40     for (int i=head[u];i!=-1;i=next[i])
     41     {
     42         int v=rea[i];
     43         if (deep[v]>deep[u]&&size[v]>size[k]) k=v;
     44     }
     45     if (k==0) return;
     46     dfs_make(k,chain);
     47     for (int i=head[u];i!=-1;i=next[i])
     48     {
     49         int v=rea[i];
     50         if (deep[v]>deep[u]&&v!=k) dfs_make(v,v);
     51     }
     52 }
     53 int lca(int a,int b)
     54 {
     55     if (deep[a]<deep[b]) swap(a,b);
     56     int i;
     57     for (i=0;(1<<i)<=deep[a];i++);
     58     i--;
     59     for (int j=i;j>=0;j--)
     60         if (deep[a]-(1<<j)>=deep[b]) a=fa[a][j];
     61     if (a==b) return a;
     62     for (int j=i;j>=0;j--)
     63         if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j];
     64     return fa[a][0];        
     65 }
     66 void updata_down(int l,int r,int p)
     67 {
     68     int tag=tr[p].tag;tr[p].tag=-1;
     69     if (tag==-1||l==r) return;
     70     tr[p<<1].num=tr[p<<1|1].num=1;
     71     tr[p<<1].tag=tr[p<<1|1].tag=tag;
     72     tr[p<<1].lc=tr[p<<1].rc=tag;
     73     tr[p<<1|1].lc=tr[p<<1|1].rc=tag;
     74 }
     75 void updata_up(int l,int r,int p)
     76 {
     77     tr[p].lc=tr[p<<1].lc,tr[p].rc=tr[p<<1|1].rc;
     78     tr[p].num=tr[p<<1].num+tr[p<<1|1].num;
     79     if (tr[p<<1].rc==tr[p<<1|1].lc) tr[p].num--;
     80 }
     81 void change(int l,int r,int p,int x,int y,int z)
     82 {
     83     updata_down(l,r,p);
     84     if (l==x&&y==r)
     85     {tr[p].num=1,tr[p].lc=tr[p].rc=tr[p].tag=z;return;}
     86     int mid=(l+r)>>1;
     87     if (y<=mid) change(l,mid,p<<1,x,y,z);
     88     else if (x>mid) change(mid+1,r,p<<1|1,x,y,z);
     89     else change(l,mid,p<<1,x,mid,z),change(mid+1,r,p<<1|1,mid+1,y,z);
     90     updata_up(l,r,p);
     91 }
     92 int query(int l,int r,int p,int x,int y)
     93 {
     94     updata_down(l,r,p);
     95     if (l==x&&y==r) return tr[p].num;
     96     int mid=(l+r)>>1,res;
     97     if (y<=mid) res=query(l,mid,p<<1,x,y);
     98     else if (x>mid) res=query(mid+1,r,p<<1|1,x,y);
     99     else
    100     {
    101         res=query(l,mid,p<<1,x,mid)+query(mid+1,r,p<<1|1,mid+1,y);
    102         if (tr[p<<1].rc==tr[p<<1|1].lc) res--;
    103     }
    104     return res;
    105 }
    106 int find(int l,int r,int p,int x)
    107 {
    108     updata_down(l,r,p);
    109     if (l==r) return tr[p].lc;
    110     int mid=(l+r)>>1;
    111     if (x<=mid) return find(l,mid,p<<1,x);
    112     else return find(mid+1,r,p<<1|1,x);
    113 }
    114 int solvequery(int x,int fq)
    115 {
    116     int res=0;
    117     while(bel[x]!=bel[fq])
    118     {
    119         res+=query(1,n,1,pos[bel[x]],pos[x]);
    120         if (find(1,n,1,pos[bel[x]])==find(1,n,1,pos[fa[bel[x]][0]])) res--;
    121         x=fa[bel[x]][0];
    122     }
    123     res+=query(1,n,1,pos[fq],pos[x]);
    124     return res;
    125 }
    126 void solvechange(int x,int fq,int z)
    127 {
    128     while(bel[x]!=bel[fq])
    129     {
    130         change(1,n,1,pos[bel[x]],pos[x],z);
    131         x=fa[bel[x]][0];
    132     }
    133     change(1,n,1,pos[fq],pos[x],z);
    134 }
    135 int main()
    136 {
    137     memset(head,-1,sizeof(head));tr[1].tag=-1;
    138     scanf("%d%d",&n,&m);
    139     for(int i=1;i<=n;i++)
    140         scanf("%d",&a[i]);
    141     int x,y,z;
    142     for (int i=1;i<n;i++)
    143     {
    144         scanf("%d%d",&x,&y);
    145         add(x,y),add(y,x);
    146     }
    147     dfs_init(1);
    148     dfs_make(1,1);
    149     for (int i=1;i<=n;i++)
    150         change(1,n,1,pos[i],pos[i],a[i]);            
    151 //==============================================================
    152     for (int i=1;i<=m;i++)
    153     {
    154         scanf("%s",ch);
    155         if (ch[0]=='Q')
    156         {
    157             scanf("%d%d",&x,&y);
    158             int par=lca(x,y);
    159             printf("%d
    ",solvequery(x,par)+solvequery(y,par)-1); 
    160         }
    161         else
    162         {
    163             scanf("%d%d%d",&x,&y,&z);
    164             int par=lca(x,y);
    165             solvechange(x,par,z),solvechange(y,par,z);
    166         }
    167     }
    168 }
  • 相关阅读:
    Delphi FileGetAttr 返回文件名的文件属性。
    SQL 执行存储过程之 [sp_executesql] 重用SQL
    Delphi XE UniGUI 部署(加载页面只出现 loading )
    chm文件转html 的简单方法
    Delphi 字符串替换 SysUtils.StringReplace
    SQL 系统进程的运行(status)状态(Runnable、Running、Suspended、Sleeping、Pending、Dormant、Background、Spinlock)
    Delphi XE UniGUI 错误:Neither DSN nor SERVER keyword supplied
    vlc 命令行
    202232 编译opencv4.5.5 win32版本
    easyocr报错
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7699949.html
Copyright © 2020-2023  润新知