zoukankan      html  css  js  c++  java
  • [SDOI2011]染色(信息学奥赛一本通 1563)(洛谷 2486)

    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]之间。


    --->题目是复制过来的,感觉字体大小很奇怪啊...不管了,先把这道鸽了我好几天的题A掉

    这道题呢主要是运用树链剖分线段树的思想

    我们用tree这个结构体来维护线段树中每个节点的左端点的颜色lc、右端点的颜色rc、区间标记col(别忘了标记下传)以及该区间颜色段的数量sum

    以下几点需要特别注意(本题难点):

    • 在区间合并的时候,如果左子树的右端右子树的左端颜色一致,那么该区间sum--;

    • 在剖链的时候,如果上一条链的左端(即靠近根节点的一端,因为在建树的时候,线段树中越左边的位置越靠近根节点)颜色和当前剖到的链的右段(即远离根节点的一端,两链相交处)颜色一致,那么总颜色数sum--;

    • top[x]==top[y],即两点已经在同一条重链上时,两边端点的颜色都应与对应的点进行比较,如颜色一致,同样总颜色数sum--;

    详情请见代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=1e6+5,inf=0x3f3f3f3f;
      4 int next[2*N],head[2*N],to[N*2],d[N],fa[N],v[2*N],seg[4*N],rev[4*N],top[N],size[N],son[N],w[N];
      5 int n;
      6 int m,q,p,tot,cnt;
      7 int sum,ma;
      8 struct node{
      9     int lc,rc,sum,col;
     10 }tree[N];
     11 void ADD(int k,int l,int r,int v)
     12 {
     13     tree[k].lc=tree[k].rc=v;
     14     tree[k].sum=1;
     15     tree[k].col=v;
     16     return ;
     17 }
     18 void pushdown(int k,int l,int r,int mid)
     19 {
     20     if(!tree[k].col)return ;
     21     ADD(k<<1,l,mid,tree[k].col);
     22     ADD(k<<1|1,mid+1,r,tree[k].col);
     23     tree[k].col=0;
     24 }
     25 void dfs1(int s,int ff)
     26 {
     27     size[s]=1;d[s]=d[ff]+1;fa[s]=ff;
     28     for(int i=head[s],t;i,t=to[i];i=next[i])
     29     {
     30         if(t!=fa[s])
     31         {
     32             dfs1(t,s);
     33             size[s]+=size[t];
     34             if(size[t]>size[son[s]])son[s]=t;
     35         }
     36     }
     37 }
     38 void dfs2(int s)
     39 {
     40     if(son[s])
     41     {
     42         seg[son[s]]=++seg[0];
     43         top[son[s]]=top[s];
     44         rev[seg[0]]=son[s];
     45         dfs2(son[s]);
     46     }
     47     for(int i=head[s],t;t=to[i],i;i=next[i])
     48     {
     49         if(!top[t])
     50         {
     51             seg[t]=++seg[0];
     52             rev[seg[0]]=t;
     53             top[t]=t;
     54             dfs2(t);
     55         }
     56     }
     57 }
     58 void update(int k)
     59 {
     60     tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
     61     if(tree[k<<1].rc==tree[k<<1|1].lc)tree[k].sum--;
     62     tree[k].lc=tree[k<<1].lc;
     63     tree[k].rc=tree[k<<1|1].rc;
     64 }
     65 void build(int k,int l,int r)
     66 {
     67     if(l==r)
     68     {
     69         tree[k].lc=tree[k].rc=w[rev[l]];
     70         tree[k].sum=1;
     71         return ;
     72     }
     73     int mid=l+r>>1;
     74     build(k<<1,l,mid);
     75     build(k<<1|1,mid+1,r);
     76     update(k);
     77 }
     78 node query2(int k,int l,int r,int x,int y)
     79 {
     80     if(l>=x&&r<=y)
     81     {
     82         return tree[k];
     83     }
     84     int mid=l+r>>1;
     85     pushdown(k,l,r,mid);
     86     if(mid>=x)
     87     {
     88         if(mid<y)
     89         {
     90             node res,ll=query2(k<<1,l,mid,x,y),rr=query2(k<<1|1,mid+1,r,x,y);
     91             res.sum=ll.sum+rr.sum+(ll.rc==rr.lc?-1:0);
     92             res.lc=ll.lc;res.rc=rr.rc;
     93             return res;
     94         }
     95         else return query2(k<<1,l,mid,x,y);
     96     }
     97     else return query2(k<<1|1,mid+1,r,x,y);
     98 }
     99 int query1(int x,int y)
    100 {
    101     //这里可能不是很好理解,但是把a、b当做现任和备胎可能会好想一些(机房大佬lhy指点) 
    102     int sum=0,a=0,b=0;
    103     int fx=top[x],fy=top[y];
    104     while(fx!=fy)
    105     {
    106         if(d[fx]<d[fy])swap(x,y),swap(fx,fy),swap(a,b);
    107         node res=query2(1,1,n,seg[fx],seg[x]);
    108         sum+=res.sum;
    109         if(res.rc==a)sum--;
    110         a=res.lc;
    111         x=fa[fx];fx=top[x];
    112     }
    113     if(d[x]>d[y])swap(x,y),swap(a,b);
    114     node res=query2(1,1,n,seg[x],seg[y]);
    115     sum+=res.sum;
    116     if(res.lc==a) sum--;
    117     if(res.rc==b) sum--;
    118     return sum;
    119 }
    120 int read()
    121 {
    122     int f=1;char ch;
    123     while((ch=getchar())<'0'||ch>'9')
    124         if(ch=='-')f=-1;
    125     int res=ch-'0';
    126     while((ch=getchar())>='0'&&ch<='9')
    127         res=res*10+ch-'0';
    128     return res*f;
    129 }
    130 void write(int x)
    131 {
    132     if(x<0)
    133     {
    134         putchar('-');
    135         x=-x;
    136     }
    137     if(x>9)write(x/10);
    138     putchar(x%10+'0');
    139 }
    140 void add(int x,int y)
    141 {
    142     next[++tot]=head[x];
    143     head[x]=tot;
    144     to[tot]=y;
    145 }
    146 void change2(int k,int l,int r,int x,int y,int v)
    147 {
    148     if(l>=x&&r<=y)return ADD(k,l,r,v);
    149     int mid=l+r>>1;
    150     pushdown(k,l,r,mid);
    151     if(mid>=x)change2(k<<1,l,mid,x,y,v);
    152     if(mid<y)change2(k<<1|1,mid+1,r,x,y,v);
    153     update(k);
    154 }
    155 void change1(int x,int y,int v)
    156 {
    157     int fx=top[x],fy=top[y];
    158     while(fx!=fy)
    159     {
    160         if(d[fx]<d[fy])swap(x,y),swap(fx,fy);
    161         change2(1,1,n,seg[fx],seg[x],v);
    162         x=fa[fx];fx=top[x];
    163     }
    164     if(d[x]>d[y])swap(x,y);
    165     change2(1,1,n,seg[x],seg[y],v);
    166 }
    167 int main()
    168 {
    169     n=read();m=read();
    170     for(int i=1;i<=n;i++)w[i]=read();
    171     for(int i=1;i<n;i++)
    172     {
    173         int x,y;
    174         x=read();y=read();
    175         add(x,y);add(y,x);
    176     }
    177     dfs1(1,0);
    178     seg[0]=top[1]=rev[1]=seg[1]=1;
    179     dfs2(1);
    180     build(1,1,n);
    181     while(m--)
    182     {
    183         char ch;int a,b;
    184         while((ch=getchar())<'A'||ch>'Z');
    185         //这个地方读入一定要小心!我的爆零经验就是前车之鉴!!! 
    186         a=read();b=read();
    187         if(ch=='C')
    188         {
    189             int c;c=read();
    190             change1(a,b,c);
    191         }
    192         else
    193         {
    194             write(query1(a,b));
    195             putchar('
    ');
    196         }
    197     }
    198     return 0;
    199 }
    200 //硬生生凑个200行 ~(~ ̄▽ ̄)~

  • 相关阅读:
    ffmpeg+nginx+video实现rtsp流转hls流,通过H5查看监控视频
    视频支持拖动进度条播放的实现(基于nginx)
    nginx 点播mp4方法
    NGINX 添加MP4、FLV视频支持模块
    html5播放mp4视频代码
    ThreadPoolExecutor使用错误导致死锁
    Spring-Cloud-Gateway
    从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析
    使用Consul做服务发现的若干姿势
    Consul 的安装与基本使用
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/11375638.html
Copyright © 2011-2022 走看看