zoukankan      html  css  js  c++  java
  • BZOJ 2243 [SDOI2011]染色:树剖【维护路径上颜色段】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

    题意:

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

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

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

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

    题解:

      树剖。

      线段树上维护区间颜色段,每个节点:

        dat[]:当前区间的颜色段数量

        st[]:修改标记

        lc[] and rc[]:当前区间的最左端和最右端颜色

        lson[] and rson[]:左右儿子编号

      线段树部分见NOI 2007 项链工厂。

      树剖query中,每次a = par[tp[a]]往上跳之前,先判断getcol(dfsx[tp[a]]) == getcol(dfsx[par[tp[a]]])

      如果相等,上下两端合并,sum--。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <vector>
      5 #define MAX_N 1000005
      6 
      7 using namespace std;
      8 
      9 int n,m;
     10 int tot=0;
     11 int cnt=0;
     12 int c[MAX_N];
     13 int dat[MAX_N];
     14 int st[MAX_N];
     15 int lc[MAX_N];
     16 int rc[MAX_N];
     17 int lson[MAX_N];
     18 int rson[MAX_N];
     19 int par[MAX_N];
     20 int dep[MAX_N];
     21 int siz[MAX_N];
     22 int tp[MAX_N];
     23 int son[MAX_N];
     24 int dfsx[MAX_N];
     25 int idx[MAX_N];
     26 vector<int> edge[MAX_N];
     27 
     28 void read()
     29 {
     30     scanf("%d%d",&n,&m);
     31     for(int i=1;i<=n;i++)
     32     {
     33         scanf("%d",&c[i]);
     34     }
     35     int a,b;
     36     for(int i=1;i<n;i++)
     37     {
     38         scanf("%d%d",&a,&b);
     39         edge[a].push_back(b);
     40         edge[b].push_back(a);
     41     }
     42 }
     43 
     44 void push_down(int now)
     45 {
     46     if(st[now]!=-1)
     47     {
     48         dat[lson[now]]=dat[rson[now]]=1;
     49         st[lson[now]]=st[rson[now]]=st[now];
     50         lc[lson[now]]=rc[lson[now]]=lc[rson[now]]=rc[rson[now]]=st[now];
     51         st[now]=-1;
     52     }
     53 }
     54 
     55 void push_up(int now)
     56 {
     57     dat[now]=0;
     58     lc[now]=lc[lson[now]];
     59     rc[now]=rc[rson[now]];
     60     if(lson[now]) dat[now]+=dat[lson[now]];
     61     if(rson[now]) dat[now]+=dat[rson[now]];
     62     if(lson[now] && rson[now] && rc[lson[now]]==lc[rson[now]]) dat[now]--;
     63 }
     64 
     65 int build(int l,int r)
     66 {
     67     int rt=++tot;
     68     dat[rt]=1;
     69     st[rt]=-1;
     70     lc[rt]=c[idx[l]];
     71     rc[rt]=c[idx[r]];
     72     lson[rt]=rson[rt]=0;
     73     if(l<r)
     74     {
     75         int mid=(l+r)>>1;
     76         lson[rt]=build(l,mid);
     77         rson[rt]=build(mid+1,r);
     78         push_up(rt);
     79     }
     80     return rt;
     81 }
     82 
     83 void update(int a,int b,int k,int l,int r,int x)
     84 {
     85     if(a<=l && r<=b)
     86     {
     87         dat[k]=1;
     88         st[k]=lc[k]=rc[k]=x;
     89         return;
     90     }
     91     if(r<a || b<l) return;
     92     push_down(k);
     93     int mid=(l+r)>>1;
     94     update(a,b,lson[k],l,mid,x);
     95     update(a,b,rson[k],mid+1,r,x);
     96     push_up(k);
     97 }
     98 
     99 int query(int a,int b,int k,int l,int r)
    100 {
    101     if(a<=l && r<=b) return dat[k];
    102     if(r<a || b<l) return 0;
    103     push_down(k);
    104     int mid=(l+r)>>1;
    105     int ans=0;
    106     if(a<=mid) ans+=query(a,b,lson[k],l,mid);
    107     if(b>mid) ans+=query(a,b,rson[k],mid+1,r);
    108     if(a<=mid && b>mid && rc[lson[k]]==lc[rson[k]]) ans--;
    109     return ans;
    110 }
    111 
    112 int getcol(int p,int k,int l,int r)
    113 {
    114     if(l==r) return lc[k];
    115     push_down(k);
    116     int mid=(l+r)>>1;
    117     if(p<=mid) return getcol(p,lson[k],l,mid);
    118     else return getcol(p,rson[k],mid+1,r);
    119 }
    120 
    121 void dfs1(int now,int p,int d)
    122 {
    123     par[now]=p;
    124     dep[now]=d;
    125     siz[now]=1;
    126     for(int i=0;i<edge[now].size();i++)
    127     {
    128         int temp=edge[now][i];
    129         if(temp!=p)
    130         {
    131             dfs1(temp,now,d+1);
    132             siz[now]+=siz[temp];
    133         }
    134     }
    135 }
    136 
    137 void dfs2(int now,int anc)
    138 {
    139     tp[now]=anc;
    140     son[now]=-1;
    141     cnt++;
    142     idx[cnt]=now;
    143     dfsx[now]=cnt;
    144     for(int i=0;i<edge[now].size();i++)
    145     {
    146         int temp=edge[now][i];
    147         if((son[now]==-1 || siz[temp]>siz[son[now]]) && temp!=par[now])
    148         {
    149             son[now]=temp;
    150         }
    151     }
    152     if(son[now]!=-1) dfs2(son[now],anc);
    153     for(int i=0;i<edge[now].size();i++)
    154     {
    155         int temp=edge[now][i];
    156         if(temp!=par[now] && temp!=son[now]) dfs2(temp,temp);
    157     }
    158 }
    159 
    160 void update_chain(int a,int b,int x)
    161 {
    162     while(tp[a]!=tp[b])
    163     {
    164         if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
    165         update(dfsx[tp[a]],dfsx[a],1,1,n,x);
    166         a=par[tp[a]];
    167     }
    168     if(dep[a]<dep[b]) swap(a,b);
    169     update(dfsx[b],dfsx[a],1,1,n,x);
    170 }
    171 
    172 int query_chain(int a,int b)
    173 {
    174     int sum=0;
    175     while(tp[a]!=tp[b])
    176     {
    177         if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
    178         sum+=query(dfsx[tp[a]],dfsx[a],1,1,n);
    179         if(getcol(dfsx[tp[a]],1,1,n)==getcol(dfsx[par[tp[a]]],1,1,n)) sum--;
    180         a=par[tp[a]];
    181     }
    182     if(dep[a]<dep[b]) swap(a,b);
    183     sum+=query(dfsx[b],dfsx[a],1,1,n);
    184     return sum;
    185 }
    186 
    187 void work()
    188 {
    189     dfs1(1,-1,0);
    190     dfs2(1,1);
    191     build(1,n);
    192     char s[16];
    193     int a,b,c;
    194     while(m--)
    195     {
    196         scanf("%s",s);
    197         if(s[0]=='Q')
    198         {
    199             scanf("%d%d",&a,&b);
    200             printf("%d
    ",query_chain(a,b));
    201         }
    202         else
    203         {
    204             scanf("%d%d%d",&a,&b,&c);
    205             update_chain(a,b,c);
    206         }
    207     }
    208 }
    209 
    210 int main()
    211 {
    212     read();
    213     work();
    214 }
  • 相关阅读:
    Material Design系列第八篇——Creating Lists and Cards
    Androidの解决自动旋转导致activity重启问题
    cnBlogs博客推荐
    yii中sphinx,Ajax搜索分页
    yii框架中应用jquery表单验证插件
    百度一键分享
    yii框架中邮箱激活(数字签名)
    yii框架中保存第三方登录信息
    yii添加行的增删改查
    yii遍历行下的每列数据(小1月考)
  • 原文地址:https://www.cnblogs.com/Leohh/p/7943011.html
Copyright © 2011-2022 走看看