1. 程式人生 > >BZOJ2243: [SDOI2011]染色

BZOJ2243: [SDOI2011]染色

scu 節點數 scrip 區間 eof wap con odi pos

2243: [SDOI2011]染色

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 8402 Solved: 3151
[Submit][Status][Discuss]

Description

給定一棵有n個節點的無根樹和m個操作,操作有2類:

1、將節點a到節點b路徑上所有點都染成顏色c

2、詢問節點a到節點b路徑上的顏色段數量(連續相同顏色被認為是同一段),如“112221”由3段組成:“11”、“222”和“1”。

請你寫一個程序依次完成這m

個操作。

Input

第一行包含2個整數nm,分別表示節點數和操作數;

第二行包含n個正整數表示n個節點的初始顏色

下面行每行包含兩個整數xy,表示xy之間有一條無向邊。

下面行每行描述一個操作:

“C a b c”表示這是一個染色操作,把節點a到節點b路徑上所有點(包括ab)都染成顏色c

“Q a b”表示這是一個詢問操作,詢問節點a到節點b(包括ab)路徑上的顏色段數量。

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]之間。

思路{

  顏色段發現用樹鏈剖分的時候記錄一下區間左右端點,比較一下就可以了.

  有點碼.....

}

#include<bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define db double
#define N 100010
using namespace std;
int w[N];
struct ed{int nxt,to;}e[N*2];
int head[N],tot,n,m;
void LINK(int u,int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;}
void link(int u,int v){LINK(u,v),LINK(v,u);}
namespace Tree{
#define ls (o<<1)
#define rs ((o<<1)|1)
#define mid ((l+r)>>1)
  int id[N],top[N],deep[N],idw[N],fa[N],sz[N],hson[N],idn;
  int Sum[N*4],lc[N*4],rc[N*4],lazy[N*4];
  void dfs1(int u,int faa){
    deep[u]=deep[faa]+1;fa[u]=faa;sz[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)if(e[i].to!=faa){
    int v=e[i].to;dfs1(v,u);
    sz[u]+=sz[v];if(sz[v]>sz[hson[u]])hson[u]=v;
      }
  }
  void dfs2(int u,int toop){
    id[u]=++idn;idw[idn]=w[u];top[u]=toop;
    if(hson[u])dfs2(hson[u],toop);
    for(int i=head[u];i!=-1;i=e[i].nxt)
      if(e[i].to!=hson[u]&&e[i].to!=fa[u])
    dfs2(e[i].to,e[i].to);
  }
  void up(int o){
    Sum[o]=Sum[ls]+Sum[rs];
    if(rc[ls]==lc[rs])Sum[o]--;
    rc[o]=rc[rs],lc[o]=lc[ls];
  }
  void build(int o,int l,int r){
    if(l==r){Sum[o]=1,rc[o]=lc[o]=idw[l];return;}
    build(rs,mid+1,r),build(ls,l,mid);
    up(o);
  }
  void down(int o){
    if(lazy[o]){
      Sum[rs]=Sum[ls]=1;
      rc[rs]=lc[rs]=lazy[rs]=lazy[o];
      rc[ls]=lc[ls]=lazy[ls]=lazy[o];
      lazy[o]=0;
    }
  }
  void Modify(int o,int l,int r,int L,int R,int c){
    if(l!=r)down(o);
    if(l>=L&&r<=R){
      Sum[o]=1;
      rc[o]=lc[o]=lazy[o]=c;
      return;
    }
    if(mid<L)Modify(rs,mid+1,r,L,R,c);
    else if(mid>=R)Modify(ls,l,mid,L,R,c);
    else Modify(rs,mid+1,r,mid,R,c),Modify(ls,l,mid,L,mid,c);
    up(o);
  }
  int Query(int o,int l,int r,int L,int R){
    if(l!=r)down(o);
    if(l>=L&&r<=R)return Sum[o];
    if(mid<L)return Query(rs,mid+1,r,L,R);
    if(mid>=R)return Query(ls,l,mid,L,R);
    else return Query(rs,mid+1,r,L,R)+Query(ls,l,mid,L,R)-(rc[ls]==lc[rs]);
  }
  int Querycol(int o,int l,int r,int pos){
    if(l!=r)down(o);if(l==r)return rc[o];
    if(mid<pos)return Querycol(rs,mid+1,r,pos);
    else return Querycol(ls,l,mid,pos);
  }
  void work1(int x,int y,int c){
    while(top[x]!=top[y]){
      if(deep[top[x]]<deep[top[y]])swap(x,y);
      Modify(1,1,n,id[top[x]],id[x],c);
      x=fa[top[x]];
    }
    if(deep[x]>deep[y])swap(x,y);
    Modify(1,1,n,id[x],id[y],c);
  }
  void work2(int x,int y){
    ll sum(0);
    while(top[x]!=top[y]){
      if(deep[top[x]]<deep[top[y]])swap(x,y);
      sum+=Query(1,1,n,id[top[x]],id[x]);
      if(Querycol(1,1,n,id[top[x]])==Querycol(1,1,n,id[fa[top[x]]]))sum--;
      x=fa[top[x]];
    }
    if(deep[x]>deep[y])swap(x,y);
    sum+=Query(1,1,n,id[x],id[y]);
    cout<<sum<<"\n";
  }
}
char C[2];
int main(){
  memset(head,-1,sizeof(head));
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;++i)scanf("%d",&w[i]);
  for(int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v),link(u,v);}
  Tree::dfs1(1,1),Tree::dfs2(1,1);Tree::build(1,1,n);
  for(int i=1;i<=m;++i){
    scanf("%s",C);
    if(C[0]==‘C‘){
      int a,b,c;scanf("%d%d%d",&a,&b,&c);
      Tree::work1(a,b,c);
    }
    else {
      int a,b;scanf("%d%d",&a,&b);
      Tree::work2(a,b);
    }
  }
  return 0;
}

BZOJ2243: [SDOI2011]染色