zoukankan      html  css  js  c++  java
  • POJ 2243 [SDOI2011]染色 | 树链剖分+线段树

    原题链接


    肯定是树链剖分的题啦

    树剖怎么做可以看我上一篇博客

    如果我们已经剖完了:

    然后考虑怎么维护重链和查询

    用线段树维护的时候当前区间的区间颜色个数应该等于左儿子+右儿子,但是当左儿子的右端点和右儿子的左端点颜色一样,显然区间数要减1

    所以每个节点存一下左端点的右端点颜色正常维护即可

    考虑查询,在同一重链上的点显然线段树可以解决,当top[u]!=top[v]的时候,得让deep较深的爬树,那么答案就要+=爬树那一段的区间个数

    但是有可能的是fa[top[u]]的颜色和top[u]的颜色相等,这个时候需要答案--,这样才能保证下次爬树的时候不会多算

    注意:请写单点查询询问颜色,因为fa[top[u]]和top[u]是轻链的两端,不能保证在线段树中编号连续,所以不能区间查询是否是个数是1

    修改同理,爬树的时候修改即可

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #define N 100010
      5 using namespace std;
      6 int n,m,head[N],indx[N],pos[N],fa[N],ecnt,color[N],deep[N],sz[N],top[N],a,b,c,tot,son[N];
      7 char s[N];
      8 int read()
      9 {
     10     int ret=0,neg=1;
     11     char j=getchar();
     12     for (;j>'9' || j<'0';j=getchar())
     13     if (j == '-') neg=-1;
     14     for (;j>='0' && j<='9';j=getchar())
     15     ret=ret*10+j-'0';
     16     return ret*neg;
     17 }
     18 struct adj
     19 {
     20     int nxt,v;
     21 }e[2*N];
     22 struct node
     23 {
     24     int l,r,Lcolor,Rcolor,sum,lz;
     25 }t[4*N];
     26 void add(int u,int v)//加边
     27 {
     28     e[++ecnt].v=v;
     29     e[ecnt].nxt=head[u];
     30     head[u]=ecnt;
     31     e[++ecnt].v=u;
     32     e[ecnt].nxt=head[v];
     33     head[v]=ecnt;
     34 }
     35 void dfs1(int x,int father,int d)//第一次dfs
     36 {
     37     fa[x]=father,deep[x]=d,sz[x]=1;
     38     for (int i=head[x];i;i=e[i].nxt)
     39     {
     40     int v=e[i].v;
     41     if (v==father) continue;
     42     dfs1(v,x,d+1);
     43     sz[x]+=sz[v];
     44     if (sz[son[x]]<sz[v]) son[x]=v;
     45     }
     46 }
     47 void dfs2(int x,int TOP)//第二次dfs
     48 {
     49     pos[x]=++tot;
     50     indx[tot]=x;
     51     top[x]=TOP;
     52     if (son[x]) dfs2(son[x],TOP);
     53     for (int i=head[x];i;i=e[i].nxt)
     54     {
     55     int v=e[i].v;
     56     if (v==fa[x] || v==son[x]) continue;
     57     if (v!=0) dfs2(v,v);
     58     }
     59 }
     60 void pushup(int p)//线段树更新
     61 {
     62     t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
     63     if (t[p<<1].Rcolor==t[p<<1|1].Lcolor) t[p].sum--;
     64     t[p].Lcolor=t[p<<1].Lcolor;
     65     t[p].Rcolor=t[p<<1|1].Rcolor;
     66 }
     67 void pushdown(int p)//lazy下放
     68 {
     69     if (t[p].l==t[p].r || t[p].lz==-1) return;
     70     int w=t[p].lz;
     71     t[p<<1].Lcolor=t[p<<1].Rcolor=t[p<<1|1].Lcolor=t[p<<1|1].Rcolor=t[p<<1].lz=t[p<<1|1].lz=w;
     72     t[p<<1].sum=t[p<<1|1].sum=1;
     73     t[p].lz=-1;
     74 }
     75 void build(int p,int l,int r)//建树
     76 {
     77     t[p].l=l,t[p].r=r,t[p].lz=-1;
     78     if (l==r)
     79     {
     80     t[p].Lcolor=t[p].Rcolor=color[indx[l]];
     81     t[p].sum=1;
     82     }
     83     else
     84     {
     85     int mid=l+r>>1;
     86     build(p<<1,l,mid);
     87     build(p<<1|1,mid+1,r);
     88     pushup(p);
     89     }
     90 }
     91 void modify(int p,int l,int r,int k)//区间修改
     92 {
     93     if (l==t[p].l && r==t[p].r)
     94     {
     95     t[p].sum=1;
     96     t[p].Lcolor=t[p].Rcolor=k;
     97     t[p].lz=k;
     98     return;
     99     }
    100     pushdown(p);
    101     int mid=t[p].l+t[p].r>>1;
    102     if (r<=mid)
    103     modify(p<<1,l,r,k);
    104     else if (l>mid) modify(p<<1|1,l,r,k);
    105     else
    106     modify(p<<1,l,mid,k),modify(p<<1|1,mid+1,r,k);
    107     pushup(p);
    108 }
    109 int query(int p,int l,int r)//区间询问
    110 {
    111     if (l==t[p].l && r==t[p].r)
    112     return t[p].sum;
    113     pushdown(p);
    114     int mid=t[p].l+t[p].r>>1;
    115     if (r<=mid)
    116     return query(p<<1,l,r);
    117     if (l>mid) return query(p<<1|1,l,r);
    118     int tmp=query(p<<1,l,mid)+query(p<<1|1,mid+1,r);
    119     if (t[p<<1].Rcolor==t[p<<1|1].Lcolor) tmp--;
    120     return tmp;
    121 }
    122 int Qcolor(int p,int l)//单点询问
    123 {
    124     if (t[p].l==t[p].r && t[p].l==l) return t[p].Lcolor;
    125     pushdown(p);
    126     int mid=t[p].l+t[p].r>>1;
    127     if (l<=mid) return Qcolor(p<<1,l);
    128     else return Qcolor(p<<1|1,l);
    129 }
    130 void getcolor(int a,int b,int w)//修改
    131 {
    132     while (top[a]!=top[b])//爬树
    133     {
    134     if (deep[top[a]]<deep[top[b]]) swap(a,b);
    135     modify(1,pos[top[a]],pos[a],w);
    136     a=fa[top[a]];
    137     }
    138     if (deep[a]>deep[b]) swap(a,b);
    139         modify(1,pos[a],pos[b],w);
    140 }
    141 int querycolor(int u,int v)//询问
    142 {
    143     int ret=0;
    144     while (top[u]!=top[v])
    145     {
    146     if (deep[top[u]]<deep[top[v]]) swap(u,v);
    147     ret+=query(1,pos[top[u]],pos[u]);
    148     if (Qcolor(1,pos[fa[top[u]]])==Qcolor(1,pos[top[u]])) ret--;//看题解
    149     u=fa[top[u]];
    150     }
    151     if (deep[u]>deep[v]) swap(u,v);
    152     return ret+query(1,pos[u],pos[v]);
    153 }
    154 int main()
    155 {
    156     n=read(),m=read();
    157     for (int i=1;i<=n;i++)
    158     color[i]=read();
    159     for (int i=1;i<n;i++)
    160     add(read(),read());
    161     dfs1(1,0,0);
    162     dfs2(1,1);
    163     build(1,1,n);
    164     while (m--)
    165     {
    166     scanf("%s",s);
    167     if (s[0]=='C')
    168     {
    169         a=read(),b=read(),c=read();
    170         getcolor(a,b,c);
    171     }
    172     else
    173     {
    174         scanf("%d%d",&a,&b);
    175         printf("%d
    ",querycolor(a,b));
    176     }
    177     }
    178     return 0;
    179 }
  • 相关阅读:
    网站迁移服务器后CPU、内存飙升,设置robots.txt 问题
    System.Web.Mvc 找到的程序集清单定义与程序集引用不匹配
    滑动窗口协议
    TCP拥塞控制
    计网常用协议
    TCP协议中的三次握手、四次挥手
    浏览网页的详细过程
    docker网络模式
    openstack网络
    查找算法
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7890691.html
Copyright © 2011-2022 走看看