zoukankan      html  css  js  c++  java
  • 2243. [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]之间。

    一眼:链剖
    两眼:链剖+两个区间相邻处特判
    和学长说了一句:感觉不是很难写(flag)
    然后我处理的时候是直接当区间修改时用for循环将线段树区间更新
    ……正确性当然可以保证啦……出乎意料的是并没有T飞……就T了一个点
    去隔壁请教了学长被告知要维护线段树的两端颜色……
    于是开始了漫长的调试……
    其实这个题只要想到了维护两端的值就很好搞了啊……
    哪怕像我想不到维护两端也有95可拿对不对【滑稽】

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #define MAX (150000+5)
      6 using namespace std;
      7 struct node
      8 {
      9     int down;//下传标记
     10     int sum;//该区间有几种颜色
     11     int l,r;//该区间左右端点的颜色
     12 } Segt[MAX*4];
     13 struct node1
     14 {
     15     int to;
     16     int next;
     17 } edge[MAX*2];
     18 int Father[MAX],Depth[MAX];
     19 int Sum[MAX],Son[MAX],Top[MAX];
     20 int TREE[MAX],T_NUM[MAX];
     21 int num_edge,head[MAX],n,cnt;
     22 int a[MAX];
     23 
     24 inline int get()//神TM快读,维护左右颜色前卡常用的但没卡过去
     25 {
     26     char c;
     27     int x=0,f=1;
     28     c=getchar();
     29     while (c<'0'||c>'9')
     30     {
     31         if (c=='-') f=-1;
     32         c=getchar();
     33     }
     34     while (c>='0'&&c<='9')
     35     {
     36         x=x*10+c-'0';
     37         c=getchar();
     38     }
     39     return x*f;
     40 }
     41 
     42 void add(int u,int v)
     43 {
     44     edge[++num_edge].to=v;
     45     edge[num_edge].next=head[u];
     46     head[u]=num_edge;
     47 }
     48 
     49 void Build(int node,int l,int r)
     50 {
     51     if (l==r)
     52     {
     53         Segt[node].sum=1;
     54         Segt[node].l=Segt[node].r=TREE[l];
     55     }
     56     else
     57     {
     58         int mid=(l+r)/2;
     59         Build(node*2,l,mid);
     60         Build(node*2+1,mid+1,r);//这里维护好麻烦啊……早知道写个pushup了
     61         Segt[node].l=Segt[node*2].l;
     62         Segt[node].r=Segt[node*2+1].r;
     63         Segt[node].sum=Segt[node*2].sum+Segt[node*2+1].sum-(Segt[node*2].r==Segt[node*2+1].l);
     64     }
     65 }
     66 
     67 void Pushdown(int node)
     68 {
     69     if (Segt[node].down!=0)
     70     {
     71         Segt[node*2].sum=1;//因为修改成了一个数所以肯定只有一种颜色
     72         Segt[node*2+1].sum=1;
     73 
     74         Segt[node*2].down=Segt[node].down;//down存下传的颜色编号
     75         Segt[node*2+1].down=Segt[node].down;
     76 
     77         Segt[node*2].l=Segt[node*2].r=Segt[node].down;
     78         Segt[node*2+1].l=Segt[node*2+1].r=Segt[node].down;
     79 
     80         Segt[node].down=0;
     81     }
     82 }
     83 
     84 int Query(int node,int l,int r,int l1,int r1)
     85 {
     86     if (r<l1 || l>r1)
     87         return 0;
     88     if (l1<=l && r<=r1)
     89         return Segt[node].sum;
     90     Pushdown(node);
     91     int mid=(l+r)/2;
     92     int x=Query(node*2,l,mid,l1,r1);
     93     int y=Query(node*2+1,mid+1,r,l1,r1);
     94     if (x!=0 && y!=0)
     95         return x+y-(Segt[node*2].r==Segt[node*2+1].l);
     96     return max(x,y);
     97 }
     98 
     99 void Update(int node,int l,int r,int l1,int r1,int k)//区间更新模板
    100 {
    101     if (r<l1 || l>r1)
    102         return;
    103     if (l1<=l && r<=r1)
    104     {
    105         Segt[node].down=k;
    106         Segt[node].sum=1;
    107         Segt[node].l=Segt[node].r=k;
    108         return;
    109     }
    110     Pushdown(node);
    111     int mid=(l+r)/2;
    112     Update(node*2,l,mid,l1,r1,k);
    113     Update(node*2+1,mid+1,r,l1,r1,k);//再一次后悔没写pushup
    114     Segt[node].l=Segt[node*2].l;
    115     Segt[node].r=Segt[node*2+1].r;
    116     Segt[node].sum=Segt[node*2].sum+Segt[node*2+1].sum-(Segt[node*2].r==Segt[node*2+1].l);
    117 }
    118 
    119 int Ask(int node,int l,int r,int x)//查询某个点的颜色
    120 {
    121     if (l==r)
    122         return Segt[node].l;
    123     else
    124     {
    125         Pushdown(node);
    126         int mid=(l+r)/2;
    127         if (x<=mid)    return Ask(node*2,l,mid,x);
    128         else return Ask(node*2+1,mid+1,r,x);
    129     }
    130 }
    131 
    132 int Get(int x,int y)
    133 {
    134     int fx=Top[x],fy=Top[y];
    135     int Ans=0;
    136     while (fx!=fy)
    137     {
    138         if (Depth[fx]<Depth[fy])
    139             swap(fx,fy),swap(x,y);
    140         int re=Ask(1,1,n,T_NUM[fx]);
    141         int fun=Ask(1,1,n,T_NUM[Father[fx]]);
    142         Ans+=Query(1,1,n,T_NUM[fx],T_NUM[x])-(re==fun);
    143         x=Father[fx],fx=Top[x];
    144     }
    145     if (Depth[x]<Depth[y])
    146         swap(x,y);
    147     return Ans+=Query(1,1,n,T_NUM[y],T_NUM[x]);
    148 }
    149 
    150 void Change(int x,int y,int k)
    151 {
    152     int fx=Top[x],fy=Top[y];
    153     while (fx!=fy)
    154     {
    155         if (Depth[fx]<Depth[fy])
    156             swap(fx,fy),swap(x,y);
    157         Update(1,1,n,T_NUM[fx],T_NUM[x],k);
    158         x=Father[fx],fx=Top[x];
    159     }
    160     if (Depth[x]<Depth[y])
    161         swap(x,y);
    162     Update(1,1,n,T_NUM[y],T_NUM[x],k);
    163 }
    164 
    165 void Dfs1(int x)
    166 {
    167     Depth[x]=Depth[Father[x]]+1;
    168     Sum[x]=1;
    169     for (int i=head[x]; i!=0; i=edge[i].next)
    170         if (edge[i].to!=Father[x])
    171         {
    172             Father[edge[i].to]=x;
    173             Dfs1(edge[i].to);
    174             Sum[x]+=Sum[edge[i].to];
    175             if (Son[x]==0 || Sum[Son[x]]<Sum[edge[i].to])
    176                 Son[x]=edge[i].to;
    177         }
    178 }
    179 
    180 void Dfs2(int x,int pre)
    181 {
    182     TREE[++cnt]=a[x];
    183     T_NUM[x]=cnt;
    184     Top[x]=pre;
    185     if (Son[x]!=0)
    186         Dfs2(Son[x],pre);
    187     for (int i=head[x]; i!=0; i=edge[i].next)
    188         if (edge[i].to!=Son[x] && edge[i].to!=Father[x])
    189             Dfs2(edge[i].to,edge[i].to);
    190 }
    191 
    192 int main()
    193 {
    194     char ch;
    195     int x,y,k,m,u,v;
    196     n=get();
    197     m=get();
    198     for (int i=1; i<=n; ++i)
    199         a[i]=get();
    200     for (int i=1; i<=n-1; ++i)
    201     {
    202         u=get();
    203         v=get();
    204         add(u,v);
    205         add(v,u);
    206     }
    207     Dfs1(1);
    208     Father[1]=1;
    209     Dfs2(1,1);
    210     Build(1,1,n);
    211     for (int i=1; i<=m; ++i)
    212     {
    213         ch=getchar();
    214         while (ch!='C'&&ch!='Q') ch=getchar();
    215         if (ch=='Q')
    216             x=get(),y=get(),printf("%d
    ",Get(x,y));
    217         else
    218             x=get(),y=get(),k=get(),Change(x,y,k);
    219     }
    220 }
  • 相关阅读:
    python测试开发django(16)--admin后台中文版
    python测试开发django(15)--admin后台管理,python3.7与django3.06冲突,降低django为2.2
    python测试开发django(14)--JsonResponse返回中文编码问题
    python测试开发django(13)--查询结果转json(serializers)
    python测试开发django(12)--ORM查询表结果
    [二分,multiset] 2019 Multi-University Training Contest 10 Welcome Party
    [概率] HDU 2019 Multi-University Training Contest 10
    [dfs] HDU 2019 Multi-University Training Contest 10
    [bfs,深度记录] East Central North America Regional Contest 2016 (ECNA 2016) D Lost in Translation
    [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
  • 原文地址:https://www.cnblogs.com/refun/p/8678489.html
Copyright © 2011-2022 走看看