首页 > 代码库 > BZOJ 2243: [SDOI2011]染色 [树链剖分]

BZOJ 2243: [SDOI2011]染色 [树链剖分]

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 6651  Solved: 2432
[Submit][Status][Discuss]

Description

 

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

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

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

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

 

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

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

下面 行每行包含两个整数x和y,表示xy之间有一条无向边。

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

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

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

 

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

 

Source

第一轮day1


 

裸树链剖分

太愚蠢了我说怎么全WA最后发现建树时给线段树的节点分配颜色弄错了

 

线段树就是普通的颜色覆盖而已,注意两个重链之间判断颜色相同

加了那个普通的标记剪枝,就bzoj rank16了

////  main.cpp//  sdoi2011染色////  Created by Candy on 2016/12/14.//  Copyright © 2016年 Candy. All rights reserved.//#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lc o<<1#define rc o<<1|1#define m ((l+r)>>1)#define lson o<<1,l,m#define rson o<<1|1,m+1,rconst int N=1e5+5;int read(){    char c=getchar();int x=0,f=1;    while(c<0||c>9){if(c==-)f=-1; c=getchar();}    while(c>=0&&c<=9){x=x*10+c-0; c=getchar();}    return x*f;}int n,Q,ww[N],w[N],x,y,a,b,c;char s[10];struct edge{    int v,ne;}e[N<<1];int h[N],cnt;inline void ins(int u,int v){    cnt++;    e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;    cnt++;    e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;}int top[N],size[N],tid[N],tot,fa[N],deep[N],mx[N];void dfs(int u){    size[u]++;    for(int i=h[u];i;i=e[i].ne){        int v=e[i].v;        if(v==fa[u]) continue;        fa[v]=u;deep[v]=deep[u]+1;        dfs(v);        size[u]+=size[v];        if(size[v]>size[mx[u]]) mx[u]=v;    }}void dfs(int u,int anc){    if(!u) return;    tid[u]=++tot;top[u]=anc;    dfs(mx[u],anc);    for(int i=h[u];i;i=e[i].ne)        if(e[i].v!=fa[u]&&e[i].v!=mx[u]) dfs(e[i].v,e[i].v);}struct node{    int lv,rv,cnt,tag;}t[N<<2];inline void merge(int o){    t[o].tag=-1;    t[o].lv=t[lc].lv;    t[o].rv=t[rc].rv;    t[o].cnt=t[lc].cnt+t[rc].cnt-(t[lc].rv==t[rc].lv);}inline void paint(int o,int v){    t[o].tag=t[o].lv=t[o].rv=v;    t[o].cnt=1;}void build(int o,int l,int r){    if(l==r) paint(o,w[l]);    else{        build(lson);        build(rson);        merge(o);    }}inline void pushDown(int o){    if(t[o].tag!=-1){        paint(lc,t[o].tag);        paint(rc,t[o].tag);        t[o].tag=-1;    }}void change(int o,int l,int r,int ql,int qr,int v){    if(ql<=l&&r<=qr) paint(o,v);    else{        pushDown(o);        if(ql<=m) change(lson,ql,qr,v);        if(m<qr) change(rson,ql,qr,v);        merge(o);    }}int query(int o,int l,int r,int ql,int qr){    if(ql<=l&&r<=qr) return t[o].cnt;    else if(t[o].tag!=-1) return 1;    else{        pushDown(o);        int ans=0;        if(ql<=m) ans+=query(lson,ql,qr);        if(m<qr) ans+=query(rson,ql,qr);        if(ql<=m&&m<qr&&t[lc].rv==t[rc].lv) ans--;        return ans;    }}int getcol(int o,int l,int r,int p){    if(l==r) return t[o].lv;    else if(t[o].tag!=-1) return t[o].tag;    else{        if(p<=m) return getcol(lson,p);        else return getcol(rson,p);    }}void sol1(int x,int y,int c){    while(top[x]!=top[y]){        if(deep[top[x]]<deep[top[y]]) swap(x,y);        change(1,1,n,tid[top[x]],tid[x],c);        x=fa[top[x]];    }    if(tid[x]>tid[y]) swap(x,y);    change(1,1,n,tid[x],tid[y],c);}int sol2(int x,int y){    int ans=0;    while(top[x]!=top[y]){        if(deep[top[x]]<deep[top[y]]) swap(x,y);        ans+=query(1,1,n,tid[top[x]],tid[x]);        if(getcol(1,1,n,tid[top[x]])==getcol(1,1,n,tid[fa[top[x]]])) ans--;        x=fa[top[x]];    }    if(tid[x]>tid[y]) swap(x,y);    ans+=query(1,1,n,tid[x],tid[y]);    return ans;}int main(int argc, const char * argv[]) {    n=read();Q=read();    for(int i=1;i<=n;i++) ww[i]=read();    for(int i=1;i<=n-1;i++) x=read(),y=read(),ins(x,y);    dfs(1);dfs(1,1);    for(int i=1;i<=n;i++) w[tid[i]]=ww[i];    build(1,1,n);    while(Q--){        scanf("%s",s);a=read();b=read();        if(s[0]==C){            c=read();sol1(a,b,c);        }else printf("%d\n",sol2(a,b));    }    return 0;}

 

 

 

BZOJ 2243: [SDOI2011]染色 [树链剖分]