• LOJ10141染色


    SDOI 2011 染色

    给定一棵有 n 个节点的无根树和 m 个操作,操作共两类。

    将节点 a 到节点 b 路径上的所有节点都染上颜色;

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

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

    输入格式
    第一行包括两个整数 n,m,表示节点数和操作数;

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

    接下来若干行包含两个整数 x 和 y,表示 x 和 y 之间有一条无向边;

    接下来若干行每行描述一个操作:

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

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

    输出格式
    对于每个询问操作,输出一行询问结果。

    样例
    样例输入
    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
    样例输出
    3
    1
    2
    数据范围与提示
    对于 100% 的数据,N,M≤10^5, 所有颜色 C 为整数且在 [0,10^9] 之间。

    _____________________________________________________________________________________

    树链剖分,需要维护

    sum[]:表示段内的色段数

    lc[]:表示左侧点的颜色

    rc[]:表示右侧点的颜色

    所以,

    sum[cur]=sum[cur<<1]+sum[cur<<1|1]-(rc[cur<<1]==lc[cur<<1|1])

    lc[cur]=lc[cur<<1]

    rc[cur]=rc[cur<<1|1]

    需要注意,树链之间两点的颜色是否相同。

    ———————————————————————————————————————————————

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1e5+10;
      4 int n,m;
      5 struct edge
      6 {
      7     int u,v,nxt;
      8 }e[maxn<<1];
      9 int head[maxn],js;
     10 void addage(int u,int v)
     11 {
     12     e[++js].u=u;e[js].v=v;
     13     e[js].nxt=head[u];head[u]=js;
     14 }
     15 int w[maxn];
     16 int dep[maxn],fat[maxn],son[maxn],siz[maxn];
     17 void dfs(int u,int fa)
     18 {
     19     dep[u]=dep[fa]+1;
     20     fat[u]=fa;
     21     siz[u]=1;
     22     for(int i=head[u];i;i=e[i].nxt)
     23     {
     24         int v=e[i].v;
     25         if(v==fa)continue;
     26         dfs(v,u);
     27         siz[u]+=siz[v];
     28         if(!son[u] || siz[son[u]]<siz[v])son[u]=v;
     29     }
     30 }
     31 int pos[maxn],fos[maxn],top[maxn],p;
     32 void getpos(int u,int fa)
     33 {
     34     pos[u]=++p;
     35     fos[p]=u;
     36     top[u]=fa;
     37     if(!son[u])return;
     38     getpos(son[u],fa);
     39     for(int i=head[u];i;i=e[i].nxt)
     40     {
     41         int v=e[i].v;
     42         if(v!=fat[u] && v!=son[u])getpos(v,v);
     43     }
     44 }
     45 int sum[maxn<<2],lc[maxn<<2],rc[maxn<<2],delt[maxn<<2];
     46 void update(int cur)
     47 {
     48     lc[cur]=lc[cur<<1];
     49     rc[cur]=rc[cur<<1|1];
     50     sum[cur]=sum[cur<<1]+sum[cur<<1|1]-(rc[cur<<1]==lc[cur<<1|1]);
     51 }
     52 void build(int cur,int l,int r)
     53 {
     54     if(l==r)
     55     {
     56         lc[cur]=rc[cur]=w[fos[l]];
     57         sum[cur]=1;
     58         return;
     59     }
     60     int mid=(l+r)>>1;
     61     build(cur<<1,l,mid);
     62     build(cur<<1|1,mid+1,r);
     63     update(cur);
     64 }
     65 void down(int cur)
     66 {
     67     sum[cur<<1]=sum[cur<<1|1]=1;
     68     delt[cur<<1]=delt[cur<<1|1]=lc[cur<<1]=rc[cur<<1]=lc[cur<<1|1]=rc[cur<<1|1]=delt[cur];
     69     delt[cur]=-1;
     70 }
     71 void modi(int cur,int l,int r,int ql,int qr,int x)
     72 {
     73     if(ql<=l && r<=qr)
     74     {
     75         sum[cur]=1;
     76         delt[cur]=lc[cur]=rc[cur]=x;
     77         return ;
     78     }
     79     int mid=(l+r)>>1;
     80     if(delt[cur]!=-1)down(cur);
     81     if(ql<=mid)modi(cur<<1,l,mid,ql,qr,x);
     82     if(mid<qr)modi(cur<<1|1,mid+1,r,ql,qr,x);
     83     update(cur);
     84 }
     85 void change(int u,int v,int x)
     86 {
     87     int tpu=top[u],tpv=top[v];
     88     while(tpu!=tpv)
     89     {
     90         if(dep[tpu]<dep[tpv])
     91         {
     92             swap(u,v);swap(tpu,tpv);
     93         }
     94         modi(1,1,n,pos[tpu],pos[u],x);
     95         u=fat[tpu];tpu=top[u];
     96     }
     97     if(dep[u]>dep[v])swap(u,v);
     98     modi(1,1,n,pos[u],pos[v],x);
     99 }
    100 int query_c(int cur,int l,int r,int p)
    101 {
    102     if(l==r)return lc[cur];
    103     int mid=(l+r)>>1;
    104     if(delt[cur]!=-1)down(cur);
    105     if(p<=mid)return query_c(cur<<1,l,mid,p);
    106     else return query_c(cur<<1|1,mid+1,r,p);
    107 }
    108 int query(int cur,int l,int r,int ql,int qr)
    109 {
    110     if(ql<=l && r<=qr)return sum[cur];
    111     int mid=(l+r)>>1,ans=0;
    112     if(delt[cur]!=-1)down(cur);
    113     if(ql<=mid)ans+=query(cur<<1,l,mid,ql,qr);
    114     if(qr>mid)ans+=query(cur<<1|1,mid+1,r,ql,qr);
    115     if(ql<=mid && mid<qr)ans-=rc[cur<<1]==lc[cur<<1|1];
    116     return ans;
    117 } 
    118 int ask(int u,int v)
    119 {
    120     int ans=0;
    121     int clt,clp;
    122     int tpu=top[u],tpv=top[v];
    123     while(tpu!=tpv)
    124     {
    125             if(dep[tpu]<dep[tpv])
    126             {
    127                 swap(u,v);swap(tpu,tpv);
    128             }
    129             clt=query_c(1,1,n,pos[tpu]);
    130             clp=query_c(1,1,n,pos[fat[tpu]]);
    131             ans+=query(1,1,n,pos[tpu],pos[u])-(clt==clp);
    132             u=fat[tpu];tpu=top[u];
    133     }
    134     if(dep[u]>dep[v])swap(u,v);
    135     ans+=query(1,1,n,pos[u],pos[v]);
    136     return ans;
    137 }
    138 int main()
    139 {
    140     scanf("%d%d",&n,&m);
    141     for(int i=1;i<=n;++i)scanf("%d",w+i);
    142     for(int u,v,i=1;i<n;++i)
    143     {
    144         scanf("%d%d",&u,&v);
    145         addage(u,v);addage(v,u);
    146     }
    147     dfs(1,0);
    148     getpos(1,1);
    149     memset(delt,-1,sizeof(delt));
    150     build(1,1,n);
    151     char s[3];
    152     int a,b,c;
    153     while(m--)
    154     {
    155         scanf("%s",s);
    156         if(s[0]=='C')
    157         {
    158             scanf("%d%d%d",&a,&b,&c);
    159             change(a,b,c);
    160         }
    161         else
    162         {
    163             scanf("%d%d",&a,&b);
    164             printf("%d
    ",ask(a,b));
    165         }
    166     }
    167     return 0;
    168 }
    View Code
  • 相关阅读:
    git 命令参考手册 git中文命令参考手册大全
    php常用命令大全
    freemarker中的list 前端模板
    jquery-懒加载技术(简称lazyload)
    JavaScript跨域总结与解决办法 什么是跨域
    Ajax+Spring MVC实现跨域请求(JSONP)JSONP 跨域
    jQuery- v1.10.2 源码解读
    css技巧
    前端异常捕获与上报
    兼容性/pollyfill/shim/渐进增强/优雅降级
  • 原文地址:https://www.cnblogs.com/gryzy/p/10479662.html
Copyright © 2020-2023  润新知