• [BZOJ2243][SDOI2011]染色


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 8463  Solved: 3168 [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]之间。

    树剖裸题

     
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 using namespace std;
      8 int n,m;
      9 int c[400005];
     10 struct data {
     11     int next,to;
     12 }e[400005];
     13 int head[400005],cnt;
     14 void add(int u,int v){e[cnt].next=head[u];e[cnt].to=v;head[u]=cnt;cnt++;}
     15 int son[400005],size[400005],fa[400005],dep[400005];
     16 void findson(int now) {
     17     size[now]=1;
     18     for(int i=head[now];i>=0;i=e[i].next) {
     19         int to=e[i].to;
     20         if(to==fa[now]) continue;
     21         fa[to]=now;
     22         dep[to]=dep[now]+1;
     23         findson(to);
     24         size[now]+=size[to];
     25         if(size[to]>size[son[now]]) son[now]=to;
     26     }
     27 }
     28 int up[400005],id[400005],p[400005],s;
     29 void dfs(int now,int top) {
     30     id[now]=++s;
     31     p[s]=now;
     32     up[now]=top;
     33     if(son[now]) dfs(son[now],top);
     34     for(int i=head[now];i>=0;i=e[i].next) {
     35         int to=e[i].to;
     36         if(to==fa[now]||to==son[now]) continue;
     37         dfs(to,to);
     38     }
     39 }
     40 struct te {
     41     int lc,rc,color,l,r,lazy;
     42 }t[800005];
     43 void pushup(int now) {
     44     int l=now<<1,r=l|1;
     45     t[now].lc=t[l].lc;t[now].rc=t[r].rc;
     46     t[now].color=t[l].color+t[r].color;
     47     if(t[l].rc==t[r].lc) t[now].color--;
     48 }
     49 void pushdown(int now) {
     50     if(!t[now].lazy) return;
     51     int l=now<<1,r=l|1;
     52     t[l].lazy=t[l].lc=t[l].rc=t[r].lazy=t[r].lc=t[r].rc=t[now].lazy;
     53     t[l].color=t[r].color=1;
     54     t[now].lazy=0;
     55 }
     56 void build(int now,int l,int r) {
     57     t[now].l=l;t[now].r=r;
     58     if(l==r){t[now].color=1;t[now].lc=t[now].rc=c[p[l]];return;}
     59     else {
     60         int mid=(l+r)>>1;
     61         build(now<<1,l,mid);
     62         build(now<<1|1,mid+1,r);
     63     }
     64     pushup(now);
     65 }
     66 void update(int now,int L,int R,int c) {
     67     int l=t[now].l,r=t[now].r;
     68     pushdown(now);
     69     if(L<=l&&R>=r){t[now].lc=t[now].rc=t[now].lazy=c;t[now].color=1;return;}
     70     else {
     71         int mid=(l+r)>>1;
     72         if(L<=mid) update(now<<1,L,R,c);
     73         if(R>mid) update(now<<1|1,L,R,c);
     74     }
     75     pushup(now);
     76 }
     77 int findlca(int a,int b) {
     78     int x,y;
     79     x=up[a],y=up[b];
     80     while(x!=y) {
     81         if(dep[x]<dep[y]) swap(x,y),swap(a,b);
     82         a=fa[x];x=up[a];
     83     }
     84     if(dep[a]<dep[b]) swap(a,b);
     85     return b;
     86 }
     87 int query(int now,int L,int R) {
     88     int ans=0;
     89     int l=t[now].l,r=t[now].r;
     90     pushdown(now);
     91     if(L<=l&&R>=r) return t[now].color;
     92     else {
     93         int mid=(l+r)>>1;
     94         if(R<=mid) ans+=query(now<<1,L,R);
     95         else if(L>mid) ans+=query(now<<1|1,L,R);
     96         else {
     97             ans+=query(now<<1,L,R)+query(now<<1|1,L,R);
     98             if(t[now<<1].rc==t[now<<1|1].lc) ans--;
     99         }
    100     }
    101     return ans;
    102 }
    103 void change(int now,int lca,int c) {
    104     while(up[now]!=up[lca]) {
    105         update(1,id[up[now]],id[now],c);
    106         now=fa[up[now]];
    107     }
    108     update(1,id[lca],id[now],c);
    109 }
    110 int getc(int now,int x) {
    111     pushdown(now);
    112     int l=t[now].l,r=t[now].r;
    113     if(l==r) return t[now].lc;
    114     int mid=(l+r)>>1;
    115     if(x<=mid)return getc(now<<1,x);
    116     else return getc(now<<1|1,x);
    117 }
    118 int ask(int now,int lca) {
    119     int ans=0;
    120     while(up[now]!=up[lca]) {
    121         ans+=query(1,id[up[now]],id[now]);
    122         if(getc(1,id[up[now]])==getc(1,id[fa[up[now]]])) ans--;
    123         now=fa[up[now]];
    124     }
    125     return ans+query(1,id[lca],id[now]);
    126 }
    127 int main() {
    128     memset(head,-1,sizeof(head));
    129     scanf("%d%d",&n,&m);
    130     for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    131     for(int i=1;i<=n-1;i++) {
    132         int u,v;
    133         scanf("%d%d",&u,&v);
    134         add(u,v);add(v,u);
    135     }
    136     dep[1]=1;
    137     findson(1);dfs(1,1);build(1,1,n);
    138     for(int i=1;i<=m;i++) {
    139         char ch[10];
    140         scanf("%s",ch);
    141         if(ch[0]=='C') {
    142             int a,b,c;
    143             scanf("%d%d%d",&a,&b,&c);
    144             int lca=findlca(a,b);
    145             change(a,lca,c);change(b,lca,c);
    146         }
    147         else {
    148                int a,b;
    149                scanf("%d%d",&a,&b);
    150                int lca=findlca(a,b);
    151                printf("%d
    ",ask(a,lca)+ask(b,lca)-1);
    152         }
    153     }
    154 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    C 语言 字符串命令 strstr()的用法 实现将原字符串以分割串分割输出
    C# 中对 IEnumerable IEnumerator yield 的理解
    C 语言 用字符输出菱形图案的函数(可自定义边长及字符样式)
    C 语言 对角线添充二维数组
    C 语言 边读 边写入文件
    [转]Page.RegisterRequiresRaiseEvent()与Page.RegisterRequiresPostBack()
    asp.net 判断是手机或电脑访问网页的方式
    表达式树【转】
    ADO.NET中的“返回多个结果集”和“MARS”【转】
    SQL2005转2000的方法【转】
  • 原文地址:https://www.cnblogs.com/wls001/p/7571409.html
Copyright © 2020-2023  润新知