• [SDOI2011]染色


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

    题解:

    树剖套路题。

    线段树维护三个参数l,r,s,分别表示左边的颜色,右边的颜色以及这段区间中颜色的总数。

    合并的时候就看一下左子树的l和右子树的r是否想等,相等就-1。

    纯粹当板子题打的,代码应该还算比较好看

      1 //Never forget why you start
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<algorithm>
      8 #define ll(x) (x<<1)
      9 #define rr(x) (x<<1|1)
     10 using namespace std;
     11 int n,m;
     12 int head[100005],size,a[100005];
     13 struct node{
     14   int next,to;
     15 }edge[200005];
     16 void putin(int from,int to){
     17   size++;
     18   edge[size].next=head[from];
     19   edge[size].to=to;
     20   head[from]=size;
     21 }
     22 int end[100005],fa[100005],depth[100005],top[100005],cnt[100005],son[100005],pos[100005],ppos[100005],dfscnt;
     23 void dfs1(int r,int father){
     24   int i;
     25   fa[r]=father;
     26   for(i=head[r];i!=-1;i=edge[i].next){
     27     int y=edge[i].to;
     28     if(y!=father){
     29       depth[y]=depth[r]+1;
     30       dfs1(y,r);
     31       cnt[r]+=cnt[y];
     32       if(son[r]==-1||cnt[y]>cnt[son[r]])son[r]=y;
     33     }
     34   }
     35   cnt[r]++;
     36 }
     37 void dfs2(int r,int tmp){
     38   int i;
     39   top[r]=tmp;
     40   pos[r]=++dfscnt;
     41   ppos[dfscnt]=r;
     42   if(son[r]!=-1)dfs2(son[r],tmp);
     43   for(i=head[r];i!=-1;i=edge[i].next){
     44     int y=edge[i].to;
     45     if(y!=fa[r]&&y!=son[r])
     46       dfs2(y,y);
     47   }
     48   end[r]=dfscnt;
     49 }
     50 struct segment{
     51   int l,r,sum,lazy;
     52   friend segment operator + (const segment a,const segment b){
     53     segment ans;
     54     if(a.sum==0)return b;
     55     if(b.sum==0)return a;
     56     ans.l=a.l;ans.r=b.r;
     57     ans.sum=a.sum+b.sum-(a.r==b.l);
     58     return ans;
     59   }
     60 }sgm[500005],zero;
     61 void push_up(int root){
     62   sgm[root].l=sgm[ll(root)].l;
     63   sgm[root].r=sgm[rr(root)].r;
     64   sgm[root].sum=sgm[ll(root)].sum+sgm[rr(root)].sum-(sgm[ll(root)].r==sgm[rr(root)].l);
     65   return;
     66 }
     67 void build(int root,int left,int right){
     68   if(left==right){
     69     sgm[root].sum=1;
     70     sgm[root].l=a[ppos[left]];
     71     sgm[root].r=a[ppos[left]];
     72     return;
     73   }
     74   if(left>right)return;
     75   int mid=(left+right)>>1;
     76   build(ll(root),left,mid);
     77   build(rr(root),mid+1,right);
     78   push_up(root);
     79 }
     80 void push_down(int root,int left,int right){
     81   if(!sgm[root].lazy)return;
     82   sgm[ll(root)].lazy=sgm[rr(root)].lazy=sgm[root].lazy;
     83   sgm[ll(root)].sum=sgm[rr(root)].sum=1;
     84   sgm[ll(root)].l=sgm[ll(root)].r=sgm[root].lazy;
     85   sgm[rr(root)].l=sgm[rr(root)].r=sgm[root].lazy;
     86   sgm[root].lazy=0;
     87   return;
     88 }
     89 void insert(int root,int left,int right,int l,int r,int v){
     90   if(l<=left&&right<=r){
     91     sgm[root].lazy=v;
     92     sgm[root].l=sgm[root].r=v;
     93     sgm[root].sum=1;
     94     return;
     95   }
     96   if(l>right||r<left)return;
     97   push_down(root,left,right);
     98   int mid=(left+right)>>1;
     99   if(l<=mid)insert(ll(root),left,mid,l,r,v);
    100   if(mid<r)insert(rr(root),mid+1,right,l,r,v);
    101   push_up(root);
    102 }
    103 segment query(int root,int left,int right,int l,int r){
    104   if(l<=left&&right<=r)
    105     return sgm[root];
    106   if(l>right||r<left)return zero;
    107   push_down(root,left,right);
    108   int mid=(left+right)>>1;
    109   segment ansl=zero,ansr=zero;
    110   if(l<=mid)ansl=query(ll(root),left,mid,l,r);
    111   if(mid<r)ansr=query(rr(root),mid+1,right,l,r);
    112   return ansl+ansr;
    113 }
    114 int query_color(int root,int left,int right,int x){
    115   if(left==right)
    116     return sgm[root].l;
    117   push_down(root,left,right);
    118   int mid=(left+right)>>1;
    119   if(x<=mid)return query_color(ll(root),left,mid,x);
    120   else return query_color(rr(root),mid+1,right,x);
    121 }
    122 void chain_add(int x,int y,int v){
    123   int f1=top[x],f2=top[y];
    124   while(f1!=f2){
    125     if(depth[f1]<depth[f2])swap(x,y),swap(f1,f2);
    126     insert(1,1,n,pos[f1],pos[x],v);
    127     x=fa[f1];f1=top[x];
    128   }
    129   if(depth[x]>depth[y])swap(x,y);
    130   insert(1,1,n,pos[x],pos[y],v);
    131 }
    132 int chain_query(int x,int y){
    133   int f1=top[x],f2=top[y],ans=0;
    134   while(f1!=f2){
    135     if(depth[f1]<depth[f2])swap(x,y),swap(f1,f2);
    136     ans+=query(1,1,n,pos[f1],pos[x]).sum;
    137     int a=query_color(1,1,n,pos[f1]);
    138     int b=query_color(1,1,n,pos[fa[f1]]);
    139     if(a==b)ans--;
    140     x=fa[f1];f1=top[x];
    141   }
    142   if(depth[x]>depth[y])swap(x,y);
    143   ans+=query(1,1,n,pos[x],pos[y]).sum;
    144   return ans;
    145 }
    146 void clean(){
    147   memset(head,-1,sizeof(head));
    148   memset(son,-1,sizeof(son));
    149   size=0;
    150 }
    151 int main(){
    152   int i,j;
    153   clean();
    154   scanf("%d%d",&n,&m);
    155   for(i=1;i<=n;i++)
    156     scanf("%d",&a[i]);
    157   for(i=1;i<n;i++){
    158     int u,v;
    159     scanf("%d%d",&u,&v);
    160     putin(u,v);
    161     putin(v,u);
    162   }
    163   depth[1]=1;
    164   dfs1(1,0);
    165   dfs2(1,0);
    166   build(1,1,n);
    167   for(i=1;i<=m;i++){
    168     char s[2];int a,b,c;
    169     scanf("%s%d%d",s,&a,&b);
    170     if(s[0]=='C'){
    171       scanf("%d",&c);
    172       chain_add(a,b,c);
    173     }
    174     else{
    175       printf("%d
    ",chain_query(a,b));
    176     }
    177   }
    178   return 0;
    179 }
  • 相关阅读:
    BootStrap 智能表单系列 五 表单依赖插件处理
    BootStrap 智能表单系列 四 表单布局介绍
    BootStrap 智能表单系列 三 分块表单配置的介绍
    LinQ.OrderBy 多个字段排序
    ABP.NET CORE 遇到的小问题
    vs2017断点无效 当前不会命中断点 已设置断点单还未绑定
    DateTime 取年月日;字符串截取
    C# DateTime 多个时间段循环相加;两个时间段求差值
    ABP.Net Core 小白使用教程 附件:ABP.NET中文文档
    ASP.NET MVC+Easyui 后台管理系统的图片上传
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8256875.html
Copyright © 2020-2023  润新知