【bzoj2243】 [SDOI2011]染色 树链剖分+线段树

来源:互联网 发布:苹果mac锁屏快捷键 编辑:程序博客网 时间:2024/05/19 03:45

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 52 2 1 2 1 11 21 32 42 52 6Q 3 5C 2 1 1Q 3 5C 5 1 2Q 3 5

Sample Output

312

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

Source

第一轮day1


如果是序列的话就是线段树傻X题吧…
改成树上,就剖一下,区间修改+区间查询而已…

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int size=1000010;int head[size],nxt[size],to[size],tot=0;void build(int f,int t){    to[++tot]=t;    nxt[tot]=head[f];    head[f]=tot;}int fa[size],sz[size],son[size],deep[size];int inseg[size],top[size];void dfs_1(int u,int f){    deep[u]=deep[f]+1;    sz[u]=1;    fa[u]=f;    for(int i=head[u];i;i=nxt[i])    {        int v=to[i];        if(v==f) continue;        dfs_1(v,u);        sz[u]+=sz[v];        if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;    }}int totp=0;void dfs_2(int u,int topu){    top[u]=topu;    inseg[u]=++totp;    if(!son[u]) return;    dfs_2(son[u],topu);    for(int i=head[u];i;i=nxt[i])    {        int v=to[i];        if(v==fa[u]||v==son[u]) continue;        dfs_2(v,v);    }}struct segment{    int l,r;    int ans,lc,rc,c;}tree[size];void update(int p){    tree[p].lc=tree[p<<1].lc;    tree[p].rc=tree[p<<1|1].rc;    if(tree[p<<1].rc==tree[p<<1|1].lc)        tree[p].ans=tree[p<<1].ans+tree[p<<1|1].ans-1;    else        tree[p].ans=tree[p<<1].ans+tree[p<<1|1].ans;}void build_tree(int p,int l,int r){    tree[p].l=l; tree[p].r=r;    if(l==r)    {        tree[p].ans=tree[p].lc=tree[p].rc=tree[p].c=0;        return ;    }    int mid=(l+r)>>1;    build_tree(p<<1,l,mid);    build_tree(p<<1|1,mid+1,r);    update(p);}void spread(int p){    if(tree[p].c)    {        tree[p<<1|1].ans=1;        tree[p<<1|1].lc=tree[p].c;        tree[p<<1|1].rc=tree[p].c;        tree[p<<1|1].c=tree[p].c;        tree[p<<1].ans=1;        tree[p<<1].lc=tree[p].c;        tree[p<<1].rc=tree[p].c;        tree[p<<1].c=tree[p].c;        tree[p].c=0;    }}void change(int p,int l,int r,int c){    if(l<=tree[p].l&&tree[p].r<=r)    {        tree[p].ans=1;        tree[p].lc=c;   tree[p].rc=c;        tree[p].c=c;        return ;    }    spread(p);    int mid=(tree[p].l+tree[p].r)>>1;    if(l<=mid) change(p<<1,l,r,c);    if(mid<r) change(p<<1|1,l,r,c);    update(p);}int ask_ans(int p,int l,int r){    if(l<=tree[p].l&&tree[p].r<=r)    {        return tree[p].ans;    }    spread(p);    int mid=(tree[p].l+tree[p].r)>>1;    int ans=0;    if(l<=mid&&mid<r)     {        if(tree[p<<1].rc==tree[p<<1|1].lc)            ans+=ask_ans(p<<1,l,mid)+ask_ans(p<<1|1,mid+1,r)-1;        else            ans+=ask_ans(p<<1,l,mid)+ask_ans(p<<1|1,mid+1,r);    }    else if(l<=mid) ans+=ask_ans(p<<1,l,r);    else if(mid<r) ans+=ask_ans(p<<1|1,l,r);    return ans;}int ask_color(int p,int x){    if(tree[p].l==tree[p].r)    {        return tree[p].lc;    }    spread(p);    int mid=(tree[p].l+tree[p].r)>>1;    if(x<=mid) return ask_color(p<<1,x);    else return ask_color(p<<1|1,x);}int find_ans(int x,int y){    int fx=top[x],fy=top[y];    int ans=0;    while(fx!=fy)    {        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);        ans+=ask_ans(1,inseg[fx],inseg[x]);        if(ask_color(1,inseg[fx])==ask_color(1,inseg[fa[fx]]))            ans--;              x=fa[fx],fx=top[x];    }    if(deep[x]>deep[y]) swap(x,y);    ans+=ask_ans(1,inseg[x],inseg[y]);    return ans;}void find_change(int x,int y,int c){    int fx=top[x],fy=top[y];    while(fx!=fy)    {        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);        change(1,inseg[fx],inseg[x],c);         x=fa[fx],fx=top[x];    }    if(deep[x]>deep[y]) swap(x,y);    change(1,inseg[x],inseg[y],c);}int data[size];int main(){    freopen("2243.in","r",stdin);    freopen("2243.out","w",stdout);    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%d",&data[i]);    }    for(int i=1;i<=n-1;i++)    {        int a,b;        scanf("%d%d",&a,&b);        build(a,b); build(b,a);    }    dfs_1(1,0); dfs_2(1,1);    build_tree(1,1,n);    for(int i=1;i<=n;i++)    {        change(1,inseg[i],inseg[i],data[i]);    }    while(m--)    {        char s[5];        scanf("%s",s);        switch(s[0])        {            case 'C':                int l,r,c;                scanf("%d%d%d",&l,&r,&c);                if(inseg[l]>inseg[r]) swap(l,r);                find_change(l,r,c);                break;            case 'Q':                int a,b;                scanf("%d%d",&a,&b);                printf("%d\n",find_ans(a,b));                               break;        }    }    return 0;}/*6 52 2 1 2 1 11 21 32 42 52 6Q 3 5C 2 1 1Q 3 5C 5 1 2Q 3 5*/
0 0
原创粉丝点击