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

     
     
    【分析】
       还是树链剖分,主要是线段树那里,要记录最左边的颜色和最右边的颜色,合并的时候看看中间相接部分颜色是否相同,如果相同ans-1.
       询问的时候是要重链、轻边的跳的,也是要记录左右的颜色,判断颜色是否相同。
     
    代码如下:
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Maxn 100010
      8 
      9 struct node
     10 {
     11     int x,y,next;
     12 }t[2*Maxn];int len=0;
     13 
     14 int c[Maxn],fa[Maxn],size[Maxn],first[Maxn],dep[Maxn];
     15 int top[Maxn],w[Maxn],son[Maxn];
     16 int wl=0;
     17 
     18 void ins(int x,int y)
     19 {
     20     t[++len].x=x;t[len].y=y;
     21     t[len].next=first[x];first[x]=len;
     22 }
     23 
     24 struct nnode
     25 {
     26     int l,r,lc,rc,cl,cr,sum,lazy;
     27 }tr[2*Maxn];int tl=0;
     28 
     29 void dfs1(int x,int f)
     30 {
     31     dep[x]=dep[f]+1;
     32     size[x]=1;fa[x]=f;son[x]=0;
     33     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
     34     {
     35         dfs1(t[i].y,x);
     36         size[x]+=size[t[i].y];
     37         if(size[t[i].y]>size[son[x]]) son[x]=t[i].y;
     38     }
     39 }
     40 
     41 void dfs2(int x,int tp)
     42 {
     43     top[x]=tp;w[x]=++wl;
     44     if(size[x]!=1) dfs2(son[x],tp);
     45     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
     46     {
     47         dfs2(t[i].y,t[i].y);
     48     }
     49 }
     50 
     51 int build(int l,int r)
     52 {
     53     int x=++tl;
     54     tr[x].l=l;tr[x].r=r;tr[x].lazy=-1;tr[x].sum=0;
     55     if(l!=r)
     56     {
     57         int mid=(l+r)>>1;
     58         tr[x].lc=build(l,mid);
     59         tr[x].rc=build(mid+1,r);
     60     }
     61     return x;
     62 }
     63 
     64 void upd(int x)
     65 {
     66     if(tr[x].lazy==-1) return;
     67     tr[x].sum=1;tr[x].cl=tr[x].cr=tr[x].lazy;
     68     if(tr[x].l!=tr[x].r)
     69     {
     70         tr[tr[x].lc].lazy=tr[x].lazy;
     71         tr[tr[x].rc].lazy=tr[x].lazy;
     72     }
     73     tr[x].lazy=-1;
     74 }
     75 
     76 void change(int x,int l,int r,int y)
     77 {
     78     if(tr[x].l==l&&tr[x].r==r)
     79     {
     80         tr[x].lazy=y;
     81         return;
     82     }
     83     upd(x);
     84     int mid=(tr[x].l+tr[x].r)>>1;
     85     if(r<=mid) change(tr[x].lc,l,r,y);
     86     else if(l>mid) change(tr[x].rc,l,r,y);
     87     else
     88     {
     89         change(tr[x].lc,l,mid,y);
     90         change(tr[x].rc,mid+1,r,y);
     91     }
     92     upd(tr[x].lc);upd(tr[x].rc);
     93     tr[x].cl=tr[tr[x].lc].cl;
     94     tr[x].cr=tr[tr[x].rc].cr;
     95     tr[x].sum=tr[tr[x].lc].sum+tr[tr[x].rc].sum;
     96     if(tr[tr[x].lc].cr==tr[tr[x].rc].cl) tr[x].sum--;
     97 }
     98 
     99 void ffind(int x,int y,int z)
    100 {
    101     int f1=top[x],f2=top[y];
    102     while(f1!=f2)
    103     {
    104         if(dep[f1]<dep[f2]) 
    105         {
    106             swap(f1,f2);
    107             swap(x,y);
    108         }
    109         change(1,w[f1],w[x],z);
    110         x=fa[f1];
    111         f1=top[x];
    112     }
    113     if(dep[x]<dep[y]) swap(x,y);
    114     change(1,w[y],w[x],z);
    115 }
    116 
    117 int q1,q2,a1,a2;
    118 int queryt(int x,int l,int r)
    119 {
    120     upd(x);
    121     if(tr[x].l==l&&tr[x].r==r)
    122     {
    123         if(q1==tr[x].l) a1=tr[x].cl;
    124         if(q2==tr[x].r) a2=tr[x].cr;
    125         return tr[x].sum;
    126     }
    127     int mid=(tr[x].l+tr[x].r)>>1;
    128     if(r<=mid) return queryt(tr[x].lc,l,r);
    129     if(l>mid) return queryt(tr[x].rc,l,r);
    130     int ans=queryt(tr[x].lc,l,mid)+queryt(tr[x].rc,mid+1,r);
    131     if(tr[tr[x].lc].cr==tr[tr[x].rc].cl) ans--;
    132     return ans;
    133 }
    134 
    135 int query(int x,int y)
    136 {
    137     int cl=-1,cr=-1,f1=top[x],f2=top[y];
    138     int ans=0;
    139     while(f1!=f2)
    140     {
    141         if(dep[f1]>=dep[f2])
    142         {
    143             q1=w[f1];q2=w[x];
    144             ans+=queryt(1,w[f1],w[x]);
    145             if(a2==cl) ans--;
    146             cl=a1;
    147             x=fa[f1];f1=top[x];
    148         }
    149         else
    150         {
    151             q1=w[f2];q2=w[y];
    152             ans+=queryt(1,w[f2],w[y]);
    153             if(a2==cr) ans--;
    154             cr=a1;
    155             y=fa[f2];f2=top[y];
    156         }
    157     }
    158     if(dep[x]<=dep[y])
    159     {
    160         q1=w[x];q2=w[y];
    161         ans+=queryt(1,w[x],w[y]);
    162         if(cl==a1) ans--;
    163         if(cr==a2) ans--;
    164     }
    165     else
    166     {
    167         q1=w[y];q2=w[x];
    168         ans+=queryt(1,w[y],w[x]);
    169         if(cr==a1) ans--;
    170         if(cl==a2) ans--;
    171     }
    172     return ans;
    173 }
    174 
    175 int main()
    176 {
    177     int n,m;
    178     scanf("%d%d",&n,&m);
    179     for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    180     memset(first,0,sizeof(first));
    181     for(int i=1;i<n;i++)
    182     {
    183         int x,y;
    184         scanf("%d%d",&x,&y);
    185         ins(x,y);ins(y,x);
    186     }
    187     dfs1(1,0);
    188     dfs2(1,1);
    189     build(1,n);
    190     for(int i=1;i<=n;i++) change(1,w[i],w[i],c[i]);
    191     char s[10];
    192     while(m--)
    193     {
    194         scanf("%s",s);
    195         if(s[0]=='Q')
    196         {
    197             int x,y;
    198             scanf("%d%d",&x,&y);
    199             printf("%d
    ",query(x,y));
    200         }
    201         else
    202         {
    203             int x,y,z;
    204             scanf("%d%d%d",&x,&y,&z);
    205             ffind(x,y,z);
    206         }
    207     }
    208     return 0;
    209 }
    [BZOJ2243]

    2016-05-12 16:34:01

     
  • 相关阅读:
    [leetcode]49. Group Anagrams变位词归类
    [leetcode]40. Combination Sum II组合之和(每元素限用一次)
    [leetcode]39. Combination Sum组合之和
    [leetcode]35. Search Insert Position寻找插入位置
    [leetcode]28. Implement strStr()实现strStr()
    [leetcode]25. Reverse Nodes in k-Group每k个节点反转一下
    [leetcode]24. Swap Nodes in Pairs交换节点对
    SVG基础知识 Adobe Illustrator绘制SVG
    Java静态方法和实例方法 java中的数组作为形参传入
    SVG可伸缩的矢量图形
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5486202.html
Copyright © 2020-2023  润新知