zoukankan      html  css  js  c++  java
  • 题解报告——[SDOI2011]染色

    传送门

    题目描述

    输入输出格式

    输入格式:

    输出格式:

    对于每个询问操作,输出一行答案。

    输入输出样例

    输入样例#1: 复制
    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
    
    输出样例#1: 复制
    3
    1
    2
    

    说明


    【思路分析】

    看到这道题得第一想法就是树剖,很显然这确实是一道树剖的板题,但是却也是一个练习树剖的很好选择,至少我做完这道题对树剖又有了新的理解,其中也有很多细节需要注意的,考验调试能力。

    首先我们用树剖维护树的链,用线段树维护链上权值。这里很好的是维护区间段数,而不是区间上的种类数,所有可以用线段树维护。

    【细节注意】

    这里我们会发现我们树剖其实是每次要将一条链分开,每一段单独进行查询,所以我们每次查询要比较这一次查询和上一段之间是否有同一段。

    由于是树剖,我们每次后查询的区间,在线段树上一定是在前面,所以我们要比较本次查询的右端点和上一次查询的左端点

    由于我们是从两个节点向LCA跳,所以我们要记录两个变量,lasta,lastb,分别表示上一次从某个方向跳来的链的端点颜色,然后进行比较即可

    【代码实现】

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 const int maxn=1e5+5;
      5 struct sd{
      6     int to,next;
      7 }edge[maxn<<1];
      8 struct sd1{
      9     int l,r,son[2],sum,lkind,rkind,lazy;
     10 }t[maxn<<2];
     11 int head[maxn],siz[maxn],top[maxn],mxson[maxn],dep[maxn],fa[maxn],id[maxn],ord[maxn],col[maxn],cnt,lnode,rnode;
     12 void update(int v)
     13 {
     14     int ls=t[v].son[0],rs=t[v].son[1];
     15     t[v].sum=t[ls].sum+t[rs].sum;
     16     if(t[ls].rkind==t[rs].lkind) t[v].sum--;
     17     t[v].lkind=t[ls].lkind,t[v].rkind=t[rs].rkind;
     18 }
     19 void pushdown(int v)
     20 {
     21     if(t[v].lazy)
     22     {
     23         int ls=t[v].son[0],rs=t[v].son[1];
     24         if(ls) t[ls].sum=1,t[ls].lazy=t[ls].lkind=t[ls].rkind=t[v].lazy;
     25         if(rs) t[rs].sum=1,t[rs].lazy=t[rs].lkind=t[rs].rkind=t[v].lazy;
     26         t[v].lazy=0;
     27     }
     28 }
     29 void build(int &v,int l,int r)
     30 {
     31     v=++cnt;t[v].l=l,t[v].r=r;
     32     if(l==r) {t[v].lkind=t[v].rkind=col[ord[l]],t[v].sum=1;return;}
     33     int mid=(l+r)>>1;
     34     build(t[v].son[0],l,mid);
     35     build(t[v].son[1],mid+1,r);
     36     update(v);
     37 }
     38 void add_edge(int from,int to)
     39 {
     40     edge[++cnt].to=to;
     41     edge[cnt].next=head[from];
     42     head[from]=cnt;
     43 }
     44 void dfs(int v,int ff,int deep)
     45 {
     46     fa[v]=ff,dep[v]=deep,siz[v]=1;
     47     int MS=0,MX=0;
     48     for(int i=head[v];i;i=edge[i].next)
     49     {
     50         int to=edge[i].to;
     51         if(to!=ff)
     52         {
     53             dfs(to,v,deep+1);
     54             if(MX<siz[to]) MX=siz[to],MS=to;
     55             siz[v]+=siz[to];
     56         }
     57     }
     58     mxson[v]=MS;
     59 }
     60 void dfs2(int v,int tt)
     61 {
     62     top[v]=tt,ord[++cnt]=v,id[v]=cnt;
     63     if(!mxson[v]) return;
     64     dfs2(mxson[v],tt);
     65     for(int i=head[v];i;i=edge[i].next)
     66     {
     67         if(edge[i].to!=fa[v]&&edge[i].to!=mxson[v])
     68             dfs2(edge[i].to,edge[i].to);
     69     }
     70 }
     71 void change(int v,int l,int r,int kk)
     72 {
     73     if(t[v].l==l&&t[v].r==r)
     74     {
     75         t[v].sum=1,t[v].lkind=t[v].rkind=t[v].lazy=kk;
     76         return;
     77     }
     78     pushdown(v);
     79     int mid=(t[v].l+t[v].r)>>1,ls=t[v].son[0],rs=t[v].son[1];
     80     if(r<=mid) change(ls,l,r,kk);
     81     else if(l>mid) change(rs,l,r,kk);
     82     else change(ls,l,mid,kk),change(rs,mid+1,r,kk);
     83     update(v);
     84 }
     85 int ask(int v,int l,int r,int ql,int qr)
     86 {
     87     pushdown(v);
     88     if(t[v].l==l&&t[v].r==r)
     89     {
     90         if(t[v].l==ql) lnode=t[v].lkind;
     91         if(t[v].r==qr) rnode=t[v].rkind;
     92         return t[v].sum;
     93     }
     94     int mid=(t[v].l+t[v].r)>>1,ls=t[v].son[0],rs=t[v].son[1];
     95     if(r<=mid) return ask(ls,l,r,ql,qr);
     96     else if(l>mid) return ask(rs,l,r,ql,qr);
     97     else 
     98     {
     99         int ans=0;
    100         ans+=ask(ls,l,mid,ql,qr);
    101         ans+=ask(rs,mid+1,r,ql,qr);
    102         if(t[ls].rkind==t[rs].lkind) ans--;
    103         return ans;
    104     }
    105 }
    106 void LCA_change(int a,int b,int kk)
    107 {
    108     while(top[a]!=top[b])
    109     {
    110         if(dep[top[a]]<dep[top[b]]) swap(a,b);
    111         change(1,id[top[a]],id[a],kk);
    112         a=fa[top[a]];
    113     }
    114     if(dep[b]<dep[a]) swap(a,b);
    115     change(1,id[a],id[b],kk);
    116 }
    117 int LCA_ask(int a,int b)
    118 {
    119     int ans=0,lasta=-1,lastb=-1;
    120     while(top[a]!=top[b])
    121     {
    122         if(dep[top[a]]>dep[top[b]])
    123         {
    124             ans+=ask(1,id[top[a]],id[a],id[top[a]],id[a]);
    125             if(rnode==lasta&&lasta!=-1) ans--;
    126             lasta=lnode;
    127             a=fa[top[a]];
    128         }
    129         else
    130         {
    131             ans+=ask(1,id[top[b]],id[b],id[top[b]],id[b]);
    132             if(rnode==lastb&&lastb!=-1) ans--;
    133             lastb=lnode;
    134             b=fa[top[b]];
    135         }
    136     }
    137     if(dep[a]<dep[b])
    138     {
    139         ans+=ask(1,id[a],id[b],id[a],id[b]);
    140         if(lasta==lnode) ans--;
    141         if(lastb==rnode) ans--;
    142      }
    143     else
    144     {
    145         ans+=ask(1,id[b],id[a],id[b],id[a]);
    146         if(lasta==rnode) ans--;
    147         if(lastb==lnode) ans--;
    148     }
    149     return ans;
    150 }
    151 int main()
    152 {
    153     int n,m,a,b,c,rt;
    154     scanf("%d%d",&n,&m);
    155     for(int i=1;i<=n;i++) scanf("%d",&col[i]);
    156     for(int i=1;i<n;i++) scanf("%d%d",&a,&b),add_edge(a,b),add_edge(b,a);
    157     cnt=0,dfs(1,0,1),dfs2(1,1);
    158     cnt=0,build(rt,1,n);
    159     while(m--)
    160     {
    161         char ch[3];
    162         scanf("%s%d%d",ch,&a,&b);
    163         if(ch[0]=='Q') printf("%d
    ",LCA_ask(a,b));
    164         else scanf("%d",&c),LCA_change(a,b,c);
    165     }
    166     return 0;
    167 }
  • 相关阅读:
    iOS编译FFmpeg、kxmovie实现视频播放 (转载)
    CocoaPods 安装 使用
    如何做优化,UITabelView才能更加顺滑 (转载)
    iOS 保持界面流畅的技巧 (转载)
    ar命令详解
    ios 静态库冲突的解决办法
    【原】IOS合并lib(.a)库的终极可用方法(可用于解决duplicate symbol静态库冲突)
    react-native 学习之TextInput组件篇
    react-native 学习之Image篇
    js 对Array的补充
  • 原文地址:https://www.cnblogs.com/genius777/p/9191465.html
Copyright © 2011-2022 走看看