题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
————————————————————————————————————————————————
2243: [SDOI2011]染色

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 7492 Solved: 2803
[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,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“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

————————————————————————————————————————————————

在树上两点间的路上进行修改 那么就是树链剖分,
根据操作 是区间染色 所以要用线段树维护

注意在维护的时候线段树上的每个点要多维护一个最左边和最右边的颜色。
方便合并的时候计算颜色个数

然后就是注意颜色可能为0
lazy标记的时候改成-1, 习惯性的用0 WA到死啊。

附本题代码

————————————————————————————————————————

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+7;

/***************************************/

int n,m;
int c[N];
vector<int >G[N];

int fa[N],sz[N],son[N],dep[N];

int dfs1(int u,int f,int d){
    fa[u]=f,sz[u]=1,son[u]=0,dep[u]=d;
    int gz = G[u].size();
    for(int to,i=0;i<gz;i++){
        to = G[u][i];
        if(to==f) continue;
        dfs1(to,u,d+1);
        sz[u]+=sz[to];
        if(sz[son[u]]<sz[to]) son[u]=to;
    }
}

int top[N],tree[N],pre[N],cnt;

int dfs2(int u,int tp){
    top[u]=tp,tree[u]=++cnt,pre[tree[u]]=u;
    if(son[u]) dfs2(son[u],tp);
    int gz = G[u].size();
    for(int to,i=0;i<gz;i++){
        to = G[u][i];
        if(to==fa[u]||to==son[u])continue;
        dfs2(to,to);
    }
}

int sum[N<<2],lazy[N<<2],lc[N<<2],rc[N<<2];

void pushup(int rt){
    sum[rt] = sum[rt<<1]+sum[rt<<1|1]-(rc[rt<<1] == lc[rt<<1|1]);
    lc[rt]=lc[rt<<1],rc[rt]=rc[rt<<1|1];
}

void pushdown(int rt){
    if(lazy[rt]!=-1){
        lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
        sum [rt<<1] = sum [rt<<1|1] = 1;
        lc[rt<<1]   = rc[rt<<1]   = lazy[rt];
        lc[rt<<1|1] = rc[rt<<1|1] = lazy[rt];
        lazy[rt]=-1;
    }
}

void build(int rt,int l,int r){
    if(l==r){
        sum[rt]=1,rc[rt]=lc[rt]=c[pre[l]];
        return ;
    }
    int m = (r+l)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
    pushup(rt);
}

void update(int rt,int r,int L,int R,int clr){
    if(L<=l&&r<=R){
        rc[rt]=lc[rt]=lazy[rt]=clr;
        sum[rt] = 1;
        return ;
    }
    pushdown(rt);
    int m = (r+l)>>1;
    if(L<=m) update(rt<<1,m,L,R,clr);
    if(R> m) update(rt<<1|1,r,clr);
    pushup(rt);
    return ;
}

int query(int rt,int R){
    if(L>R) return 0;
    if(L<=l&&r<=R) return sum[rt];
    pushdown(rt);
    int ans = 0,m = (r+l)>>1;
    if(R<=m)      ans = query(rt<<1,R);
    else if(L>m)  ans = query(rt<<1|1,R);
    else          ans = query(rt<<1,R)+
                        query(rt<<1|1,R)-
                        (rc[rt<<1]==lc[rt<<1|1]);
    pushup(rt);
    return ans;
}

int query_color(int rt,int pos){
    if(l==r)  return lc[rt];
    pushdown(rt);
    int m = (r+l)>>1,ans;
    if(pos<=m) ans = query_color(rt<<1,pos);
    else       ans = query_color(rt<<1|1,pos);
    pushup(rt);
    return ans;
}

void init(){
    cnt = 0;
    for(int i=1;i<=n;i++)G[i].clear();
    memset(sum,0,sizeof(sum));
    memset(lazy,-1,sizeof(lazy));
};

void brush(int x,int y,int clr){
    int fx = top[x],fy = top[y];
    while(fx!=fy){
        if(dep[fx]<dep[fy]) swap(fx,fy),swap(x,y);
        update(1,1,n,tree[fx],tree[x],clr);
        x = fa[fx],fx = top[x];
    }
    if(tree[x]>tree[y]) swap(x,y);
    update(1,tree[y],clr);
    return ;
}

void solve(int x,int y){
    int fx = top[x],fy = top[y];
    int ans = 0;
    while(fx!=fy){
        if(dep[fx]<dep[fy]) swap(fx,y);
        ans += query(1,tree[x]);
        if(query_color(1,tree[fa[fx]]) == query_color(1,tree[fx])) ans--;
        x = fa[fx],y);
    ans += query(1,tree[y]);
    printf("%d\n",ans);
    return ;
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        init();

        for(int i=1;i<=n;i++) scanf("%d",&c[i]);

        for(int i=2,v;i<=n;i++){
            scanf("%d %d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }

        dfs1(1,1);
        dfs2(1,1);
        build(1,n);

        int l,x;
        char a[10];
        while(m--){
            scanf("%s",a);
            scanf("%d %d",&l,&r);
            if(a[0]=='C'){
                scanf("%d",&x);
                brush(l,x);
            }
            else  solve(l,r);
        }
    }
    return 0;
}

BZOJ 2243: [SDOI2011]染色 [树链剖分+细节]【数据结构】的更多相关文章

  1. BZOJ 2243: [SDOI2011]染色 [树链剖分+细节]【数据结构】

    SampleInput652212111213242526Q35C211Q35C512Q35SampleOutput312HINT数N

随机推荐

  1. 【数据结构】单调栈

    显然,每个发射站发来的能量有可能被0或1或2个其他发射站所接受,特别是为了安全,每个发射站接收到的能量总和是我们很关心的问题。由于数据很多,现只需要你帮忙计算出接收最多能量的发射站接收的能量是多少。输入输出格式输入格式:第1行:一个整数N;第2到N+1行:第i+1行有两个整数Hi和Vi,表示第i个人发射站的高度和发射的能量值。输入输出样例输入样例:34235610输出样例:7题解中有讲解代码实现

  2. BZOJ 1798 [Ahoi2009] Seq 维护序列seq [线段树+多重标记下传]【数据结构】

    有长为N的数列,不妨设为a1,a2,…Input第一行两个整数N和P。第二行含有N个非负整数,从左到右依次为a1,aN,。表示把所有满足t≤i≤g的ai改为ai×c。操作2:“2tgc”。同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。Output对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。SampleInput7431234567512553242379313347SampleOutput2358HINT初始时数列为。对第5次操作,和为29+34+15+16=

  3. 陈越《数据结构》第一讲 基本概念

    陈越《数据结构》第一讲基本概念1什么是数据结构1.1引子例子:如何在书架上摆放图书?数据结构是:1.数据对象在计算机中的组织方式;2.数据对象必定与一系列加在其上的操作相关联;3.完成这些操作所用的方法就是算法。抽象数据类型数据类型-数据对象集;-数据集合相关联的操作集。抽象-与存放数据的机器无关;-与数据存储的物理结构无关;-与实现操作的算法和编程语言均无关。

  4. 陈越《数据结构》第二章 线性结构

    表中元素个数称为线性表的长度;线性表没有元素时,称为空表;表起始位置称表头,表结束位置称表尾。插入和删除操作只能在链栈的栈顶进行。

  5. 【数据结构】

    非线性结构:线性结构的元素之间具有线性关系,非线性结构中的元素之间不再是序列的关系,他们呈现的是更复杂的层次关系,即一个数据元素有且仅有一个直接前驱,但可有另个或者多个直接后继,显然比序列关系复杂常见非线性结构:树,图散列表PHP中的hashtable就是哈希表就是由数组和链表组成,一个长度为16的数组中,每个元素存储的是一个链表的头结点。

  6. 【数据结构】【C++STL】FIFO队列&amp;优先队列

    首先都需要打头文件queueFIFO队列是先进先出的就好像排队一样STL定义FIFO队列优先队列的话是有优先级存在的STL定义优先队列定义方式都是大根堆FIFO队列和优先队列都有一些操作COYG

  7. 【数据结构】 堆

    自底向上://增加/减少已有节点值Heap_Increase_Key//向堆插入新的节点HeapInsert自顶向下://替换堆顶后,维持堆函数KeepHeap//弹出堆顶函数Pop

  8. 【数据结构】链表

    线性表的顺序存储结构有存储密度高及能够随机存取等优点,但存在以下不足:线性表的链式存储(单链表)的实现单向循环链表的实现

  9. 伸展树(SPLAY)个人总结+模板 [平衡树]【数据结构】【模板】

    前言最近3个月内,无论是现场赛还线上赛中SPLAY出现的概率大的惊人啊啊啊!!!然而不会的我就GG了,同时发现大家都会SPLAY,,,,然后就学习了一波。——————————————————————————-附上整体代码-md贴上来太卡了,去题解里看吧维护序列的维护一堆数的

  10. BZOJ 1895 &amp; POJ 3580 supermemo [SPLAY]【数据结构】

    Ay}Ttimes.Forexample,performing“REVOLVE242”on{1,5}INSERTxP:insertPafterAx.Forexample,performing“INSERT24”on{1,5}DELETEx:deleteAx.Forexample,performing“DELETE2”on{1,5}MINxy:querytheparticipantwhatistheminimumnumberinsub-sequence{Ax…Ay}.Forexample,thecorrec

返回
顶部