• Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 5020  Solved: 1872
    [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

    题解:

    树链剖分处理一下连接点之间的颜色是否相同即可。。。

    线段树中记录 左右颜色,分成段数即可。。。

    其实LCT做这道题也是不错的呦!!!(两个程序都挂上吧。。。)

    对比:

    LCT:

    9088 kb

    17756 ms

    树链剖分:

    29944 kb 8652 ms

    树链剖分:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 100010
      4 struct node
      5 {
      6     int begin,end,next;
      7 }edge[MAXN*2];
      8 struct NODE
      9 {
     10     int left,right,lc,rc,color,tag,sum;
     11 }tree[MAXN*5];
     12 int cnt,Head[MAXN],size[MAXN],deep[MAXN],P[MAXN][17],pos[MAXN],belong[MAXN],c[MAXN],SIZE,n;
     13 bool vis[MAXN];
     14 void addedge(int bb,int ee)
     15 {
     16     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
     17 }
     18 void addedge1(int bb,int ee)
     19 {
     20     addedge(bb,ee);addedge(ee,bb);
     21 }
     22 int read()
     23 {
     24     int s=0,fh=1;char ch=getchar();
     25     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     26     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     27     return s*fh;
     28 }
     29 void dfs1(int u)
     30 {
     31     int i,v;
     32     size[u]=1;vis[u]=true;
     33     for(i=Head[u];i!=-1;i=edge[i].next)
     34     {
     35         v=edge[i].end;
     36         if(vis[v]==false)
     37         {
     38             deep[v]=deep[u]+1;
     39             P[v][0]=u;
     40             dfs1(v);
     41             size[u]+=size[v];
     42         }
     43     }
     44 }
     45 void Ycl()
     46 {
     47     int i,j;
     48     for(j=1;(1<<j)<=n;j++)
     49     {
     50         for(i=1;i<=n;i++)
     51         {
     52             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
     53         }
     54     }
     55 }
     56 void dfs2(int u,int chain)
     57 {
     58     int k=0,i,v;
     59     pos[u]=++SIZE;belong[u]=chain;
     60     for(i=Head[u];i!=-1;i=edge[i].next)
     61     {
     62         v=edge[i].end;
     63         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
     64     }
     65     if(k==0)return;
     66     dfs2(k,chain);
     67     for(i=Head[u];i!=-1;i=edge[i].next)
     68     {
     69         v=edge[i].end;
     70         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
     71     }
     72 }
     73 int LCA(int x,int y)
     74 {
     75     int i,j;
     76     if(deep[x]<deep[y])swap(x,y);
     77     for(i=0;(1<<i)<=deep[x];i++);i--;
     78     for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j];
     79     if(x==y)return x;
     80     for(j=i;j>=0;j--)
     81     {
     82         if(P[x][j]!=-1&&P[x][j]!=P[y][j])
     83         {
     84             x=P[x][j];
     85             y=P[y][j];
     86         }
     87     }
     88     return P[x][0];
     89 }
     90 void Pushup(int k)
     91 {
     92     int l=k*2,r=k*2+1;
     93     tree[k].lc=tree[l].lc;
     94     tree[k].rc=tree[r].rc;
     95     if(tree[l].rc==tree[r].lc)tree[k].sum=tree[l].sum+tree[r].sum-1;
     96     else tree[k].sum=tree[l].sum+tree[r].sum;
     97 }
     98 void Pushdown(int k)
     99 {
    100     int l=k*2,r=k*2+1;
    101     if(tree[k].tag!=-1)
    102     {
    103         tree[l].tag=tree[k].tag;
    104         tree[r].tag=tree[k].tag;
    105         tree[l].lc=tree[l].rc=tree[l].color=tree[k].tag;
    106         tree[r].lc=tree[r].rc=tree[r].color=tree[k].tag;
    107         tree[l].sum=tree[r].sum=1;
    108         tree[k].tag=-1;
    109     }
    110 }
    111 void Build(int k,int l,int r)
    112 {
    113     tree[k].left=l;tree[k].right=r;tree[k].tag=-1;
    114     if(l==r)return;
    115     int mid=(l+r)/2;
    116     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
    117 }
    118 void Change(int k,int l,int r,int C)
    119 {
    120     if(l<=tree[k].left&&tree[k].right<=r){tree[k].lc=tree[k].rc=tree[k].color=tree[k].tag=C;tree[k].sum=1;return;}
    121     Pushdown(k);
    122     int mid=(tree[k].left+tree[k].right)/2;
    123     if(r<=mid)Change(k*2,l,r,C);
    124     else if(l>mid)Change(k*2+1,l,r,C);
    125     else {Change(k*2,l,mid,C);Change(k*2+1,mid+1,r,C);}
    126     Pushup(k);
    127 }
    128 void Solve_change(int x,int f,int C)
    129 {
    130     while(belong[x]!=belong[f])
    131     {
    132         Change(1,pos[belong[x]],pos[x],C);
    133         x=P[belong[x]][0];
    134     }
    135     Change(1,pos[f],pos[x],C);
    136 }
    137 int Query_sum(int k,int l,int r)
    138 {
    139     if(l<=tree[k].left&&tree[k].right<=r)return tree[k].sum;
    140     Pushdown(k);
    141     int mid=(tree[k].left+tree[k].right)/2;
    142     if(r<=mid)return Query_sum(k*2,l,r);
    143     else if(l>mid)return Query_sum(k*2+1,l,r);
    144     //else return Query_sum(k*2,l,mid)+Query_sum(k*2+1,mid+1,r);
    145     else
    146     {
    147         if(tree[k*2].rc==tree[k*2+1].lc)return Query_sum(k*2,l,mid)+Query_sum(k*2+1,mid+1,r)-1;
    148         else return Query_sum(k*2,l,mid)+Query_sum(k*2+1,mid+1,r);
    149     }
    150     //Pushup(k);
    151 }
    152 int get_color(int k,int lr)
    153 {
    154     if(tree[k].left==tree[k].right)return tree[k].color;
    155     Pushdown(k);
    156     int mid=(tree[k].left+tree[k].right)/2;
    157     if(lr<=mid)return get_color(k*2,lr);
    158     else if(lr>mid)return get_color(k*2+1,lr);
    159 }
    160 int Solve_sum(int x,int f)
    161 {
    162     int sum=0;
    163     while(belong[x]!=belong[f])
    164     {
    165         sum+=Query_sum(1,pos[belong[x]],pos[x]);
    166         if(get_color(1,pos[belong[x]])==get_color(1,pos[P[belong[x]][0]]))sum--;
    167         x=P[belong[x]][0];
    168     }
    169     sum+=Query_sum(1,pos[f],pos[x]);
    170     return sum;
    171 }
    172 int main()
    173 {
    174     int m,i,bb,ee,A,B,C,lca;
    175     char zs[2];
    176     n=read();m=read();
    177     for(i=1;i<=n;i++)c[i]=read();
    178     memset(Head,-1,sizeof(Head));cnt=1;
    179     for(i=1;i<n;i++){bb=read();ee=read();addedge1(bb,ee);}
    180     memset(P,-1,sizeof(P));SIZE=0;
    181     dfs1(1);Ycl();
    182     dfs2(1,1);
    183     Build(1,1,n);
    184     for(i=1;i<=n;i++)Change(1,pos[i],pos[i],c[i]);
    185     for(i=1;i<=m;i++)
    186     {
    187         scanf("%s",zs);
    188         if(zs[0]=='C')
    189         {
    190             A=read();B=read();C=read();
    191             lca=LCA(A,B);
    192             Solve_change(A,lca,C);Solve_change(B,lca,C);
    193         }
    194         else
    195         {
    196             A=read();B=read();
    197             lca=LCA(A,B);
    198             printf("%d
    ",Solve_sum(A,lca)+Solve_sum(B,lca)-1);
    199         }
    200     }
    201     fclose(stdin);
    202     fclose(stdout);
    203     return 0;
    204 }

    LCT(代码略丑):

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define LL long long
      4 #define MAXN 100010
      5 #define INF 1e9
      6 struct node
      7 {
      8     LL left,right,color,tag1,lc,rc,sum;
      9 }tree[MAXN];
     10 LL rev[MAXN],father[MAXN],Stack[MAXN];
     11 LL read()
     12 {
     13     LL s=0,fh=1;char ch=getchar();
     14     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     15     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     16     return s*fh;
     17 }
     18 LL isroot(LL x)
     19 {
     20     return tree[father[x]].left!=x&&tree[father[x]].right!=x;
     21 }
     22 void pushdown(LL x)
     23 {
     24     LL l=tree[x].left,r=tree[x].right;
     25     if(rev[x]!=0)
     26     {
     27         rev[x]^=1;rev[l]^=1;rev[r]^=1;
     28         swap(tree[x].left,tree[x].right);
     29         swap(tree[x].lc,tree[x].rc);
     30         //tree[x].lc=tree[r].lc;tree[x].rc=tree[l].rc;
     31         //swap(tree[l].color,tree[r].color);
     32         //swap(tree[l].sum,tree[r].sum);
     33     }
     34     if(tree[x].tag1!=-1)
     35     {
     36         //tree[l].lc=tree[l].rc=tree[x].tag1;
     37         //tree[r].lc=tree[r].rc=tree[x].tag1;
     38         /*tree[l].color=*/tree[x].color=tree[x].lc=tree[x].rc=tree[x].tag1;
     39         tree[l].tag1=tree[r].tag1=tree[x].tag1;
     40         tree[x].sum=1;
     41         tree[x].tag1=-1;
     42     }
     43 }
     44 void pushup(LL x)
     45 {
     46     LL l=tree[x].left,r=tree[x].right;
     47     //if(tree[l].rc==tree[r].lc)
     48     //{
     49     if(l!=0)pushdown(l);
     50     if(r!=0)pushdown(r);
     51         //if(l!=0)lr+=tree[l].sum;
     52         //if(r!=0)lr+=tree[r].sum;
     53     tree[x].sum=tree[l].sum+tree[r].sum+1;
     54         if(l!=0&&tree[l].rc==tree[x].color)tree[x].sum--;
     55         if(r!=0&&tree[r].lc==tree[x].color)tree[x].sum--;
     56         //tree[x].sum=lr;
     57         tree[x].lc=tree[x].rc=tree[x].color;
     58         if(l!=0)tree[x].lc=tree[l].lc;
     59         if(r!=0)tree[x].rc=tree[r].rc;
     60         //tree[x].sum=tree[l].sum+tree[r].sum-1;
     61         //tree[x].lc=tree[l].lc;
     62         //tree[x].rc=tree[r].rc;
     63     //}
     64     //else
     65     //{
     66         //tree[x].sum=tree[l].sum+tree[r].sum;
     67         //tree[x].lc=tree[l].lc;
     68         //tree[x].rc=tree[r].rc;
     69         //if(l!=0)lr+=tree[l].sum,tree[x].lc=tree[l].lc;
     70         //if(r!=0)lr+=tree[r].sum,tree[x].rc=tree[r].rc;
     71         //if(lr!=0)tree[x].sum=lr+1;
     72     //}
     73 }
     74 void rotate(LL x)
     75 {
     76     LL y=father[x],z=father[y];
     77     if(!isroot(y))
     78     {
     79         if(tree[z].left==y)tree[z].left=x;
     80         else tree[z].right=x;
     81     }
     82     if(tree[y].left==x)
     83     {
     84         father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
     85     }
     86     else
     87     {
     88         father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
     89     }
     90     pushup(y);pushup(x);
     91 }
     92 void splay(LL x)
     93 {
     94     LL top=0,i,y,z;Stack[++top]=x;
     95     for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
     96     for(i=top;i>=1;i--)pushdown(Stack[i]);
     97     while(!isroot(x))
     98     {
     99         y=father[x];z=father[y];
    100         if(!isroot(y))
    101         {
    102             if((tree[y].left==x)^(tree[z].left==y))rotate(x);
    103             else rotate(y);
    104         }
    105         rotate(x);
    106     }
    107 }
    108 void access(LL x)
    109 {
    110     LL last=0;
    111     while(x!=0)
    112     {
    113         splay(x);
    114         tree[x].right=last;pushup(x);
    115         last=x;x=father[x];
    116     }
    117 }
    118 void makeroot(LL x)
    119 {
    120     access(x);splay(x);rev[x]^=1;
    121 }
    122 void link(LL u,LL v)
    123 {
    124     makeroot(u);father[u]=v;splay(u);
    125 }
    126 void cut(LL u,LL v)
    127 {
    128     makeroot(u);access(v);splay(v);father[u]=tree[v].left=0;
    129 }
    130 LL findroot(LL x)
    131 {
    132     access(x);splay(x);
    133     while(tree[x].left!=0)x=tree[x].left;
    134     return x;
    135 }
    136 int main()
    137 {
    138     LL i,x,y,n,m,a,b,c;
    139     char fh[2];
    140     n=read();m=read();
    141     tree[0].lc=tree[0].rc=-INF;
    142     for(i=1;i<=n;i++)tree[i].color=tree[i].lc=tree[i].rc=read(),tree[i].sum=1,tree[i].tag1=-1;
    143     for(i=1;i<n;i++)
    144     {
    145         x=read();y=read();
    146         link(x,y);
    147     }
    148     for(i=1;i<=m;i++)
    149     {
    150         scanf("
    %s",fh);
    151         if(fh[0]=='C')
    152         {
    153             a=read();b=read();c=read();
    154             makeroot(a);access(b);splay(b);
    155             tree[b].color=tree[b].lc=tree[b].rc=c;tree[b].tag1=c;
    156             tree[b].sum=1;
    157         }
    158         else
    159         {
    160             a=read();b=read();
    161             makeroot(a);access(b);splay(b);
    162             printf("%d
    ",tree[b].sum);
    163         }
    164     }
    165     return 0;
    166 }
  • 相关阅读:
    [程序员代码面试指南]递归和动态规划-换钱的方法数(DP,完全背包)
    [程序员代码面试指南]递归和动态规划-换钱的最少货币数(DP,完全背包)
    [程序员代码面试指南]数组和矩阵-未排序数组中累加和为给定值的最长子数组长度
    浅谈RDD
    Java中的移位操作符
    Boolean类源码分析
    IntegerCache详解
    Java Integer类分析
    ArrayList LinkedList Vector
    java的"=="与"equals"
  • 原文地址:https://www.cnblogs.com/Var123/p/5311546.html
Copyright © 2020-2023  润新知