zoukankan      html  css  js  c++  java
  • [SDOI2011]染色

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 11290  Solved: 4392

    题目链接

    https://www.lydsy.com/JudgeOnline/problem.php?id=2243

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

    题解

    这题也算是树链剖分的一种经典模型吧,线段树只要记录该区间最左端点的值,最右端点的值,以及该区间的段数和就可以了。

    合并的话,考虑下中间交接部分就行。

    树剖的时候每段之间再判断一下交界处即可。

    打完才发现原来再洛谷做过一遍了,竟然没有印象了,不过莫名比上次快了两秒,这次总时间3秒,上次5秒。

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define N 200050
      5 int n,m,w[N];
      6 struct Edge{int from,to,s;}edges[N<<1];
      7 int tot,last[N];
      8 struct Tree{int l,r,lazy,lb,rb,sum;}tr[N<<2];
      9 int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
     10 struct Query{int sum,lb,rb;};
     11 template<typename T>void read(T&x)
     12 {
     13   ll k=0; char c=getchar();
     14   x=0;
     15   while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
     16   if (c==EOF)exit(0);
     17   while(isdigit(c))x=x*10+c-'0',c=getchar();
     18   x=k?-x:x;
     19 }
     20 void read_char(char &c)
     21 {while(!isalpha(c=getchar())&&c!=EOF);}
     22 void AddEdge(int x,int y)
     23 {
     24   edges[++tot]=Edge{x,y,last[x]};
     25   last[x]=tot;
     26 }
     27 void push_up(int x)
     28 {
     29   Tree a=tr[x<<1],b=tr[x<<1|1];
     30   int len=tr[x].r-tr[x].l+1;
     31   if (len>1)
     32     {
     33       tr[x].sum=a.sum+b.sum-(a.rb==b.lb);
     34       tr[x].lb=a.lb;
     35       tr[x].rb=b.rb;
     36     }
     37   else tr[x].sum=0;
     38   if (tr[x].lazy!=-1)
     39     {tr[x].sum=1;tr[x].lb=tr[x].rb=tr[x].lazy;}
     40 }
     41 void push_down(int x)
     42 {
     43   if (tr[x].lazy==-1)return;
     44   tr[x<<1].lazy=tr[x].lazy;
     45   tr[x<<1|1].lazy=tr[x].lazy;
     46   push_up(x<<1);
     47   push_up(x<<1|1);
     48   tr[x].lazy=-1;
     49 }
     50 void bt(int x,int l,int r)
     51 {
     52   tr[x].l=l; tr[x].r=r; tr[x].lazy=-1;
     53   if (l==r)
     54     {
     55       tr[x].lb=tr[x].rb=w[kth[l]];
     56       tr[x].sum=1;
     57       return;
     58     }
     59   int mid=(l+r)>>1;
     60   bt(x<<1,l,mid);
     61   bt(x<<1|1,mid+1,r);
     62   push_up(x);
     63 }
     64 void update(int x,int l,int r,int tt)
     65 {
     66   if (l<=tr[x].l&&tr[x].r<=r)
     67     {
     68       tr[x].lazy=tt;
     69       push_up(x);
     70       return;
     71     }
     72   int mid=(tr[x].l+tr[x].r)>>1;
     73   push_down(x);
     74   if (l<=mid)update(x<<1,l,r,tt);
     75   if (mid<r)update(x<<1|1,l,r,tt);
     76   push_up(x);
     77 }
     78 Query query(int x,int l,int r)
     79 {
     80   if (l<=tr[x].l&&tr[x].r<=r)
     81     {
     82       return Query{tr[x].sum,tr[x].lb,tr[x].rb};
     83     }
     84   int mid=(tr[x].l+tr[x].r)>>1;
     85   Query tp1={0,-1,-1},tp2={0,-1,-1},tp;
     86   push_down(x);
     87   if (l<=mid)tp1=query(x<<1,l,r);
     88   if (mid<r)tp2=query(x<<1|1,l,r);
     89   push_up(x);
     90   tp.sum=tp1.sum+tp2.sum-(tp1.rb==tp2.lb);
     91   tp.lb=tp1.lb==-1?tp2.lb:tp1.lb;
     92   tp.rb=tp2.rb==-1?tp1.rb:tp2.rb;
     93   return tp;
     94 }
     95 void dfs1(int x,int pre)
     96 {
     97   fa[x]=pre;
     98   dp[x]=dp[pre]+1;
     99   size[x]=1;
    100   son[x]=0;
    101   for(int i=last[x];i;i=edges[i].s)
    102     {
    103       Edge &e=edges[i];
    104       if (e.to==pre)continue;
    105       dfs1(e.to,x);
    106       size[x]+=size[e.to];
    107       if (size[e.to]>size[son[x]])son[x]=e.to;
    108     }
    109 }
    110 void dfs2(int x,int y)
    111 {
    112   rk[x]=++cnt;
    113   kth[cnt]=x;
    114   top[x]=y;
    115   if(son[x]==0)return;
    116   dfs2(son[x],y);
    117   for(int i=last[x];i;i=edges[i].s)
    118     {
    119       Edge &e=edges[i];
    120       if (e.to==fa[x]||e.to==son[x])continue;
    121       dfs2(e.to,e.to);
    122     }
    123 }
    124 void change(int x,int y,int tt)
    125 {
    126   int fx=top[x],fy=top[y];
    127   while(fx!=fy)
    128     {
    129       if(dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
    130       update(1,rk[fx],rk[x],tt);
    131       x=fa[fx];fx=top[x];
    132     }
    133   if (dp[x]<dp[y])swap(x,y);
    134   update(1,rk[y],rk[x],tt);
    135 }
    136 int get_sum(int x,int y)
    137 {
    138   int fx=top[x],fy=top[y],lx=-1,ly=-1,ans=0;
    139   Query tp;
    140   while(fx!=fy)
    141     {
    142       if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy),swap(lx,ly);
    143       tp=query(1,rk[fx],rk[x]);
    144       ans+=tp.sum-(tp.rb==lx);
    145       lx=tp.lb; x=fa[fx]; fx=top[x];
    146     }
    147   if (dp[x]<dp[y])swap(x,y),swap(lx,ly);
    148   tp=query(1,rk[y],rk[x]);
    149   ans+=tp.sum-(tp.lb==ly)-(tp.rb==lx);
    150   return ans;
    151 }
    152 int main()
    153 {
    154 #ifndef ONLINE_JUDGE
    155   freopen("aa.in","r",stdin);
    156 #endif
    157   read(n); read(m);
    158   for(int i=1;i<=n;i++)read(w[i]);
    159   for(int i=1;i<=n-1;i++)
    160     {
    161       int x,y;
    162       read(x); read(y);
    163       AddEdge(x,y);
    164       AddEdge(y,x);
    165     }
    166   dfs1(1,0);
    167   dfs2(1,1);
    168   bt(1,1,n);
    169   for(int i=1;i<=m;i++)
    170     {
    171       char id; int x,y,tt;
    172       read_char(id); read(x); read(y);
    173       if(id=='C')
    174     {
    175       read(tt);
    176       change(x,y,tt);
    177     }
    178       if (id=='Q')printf("%d
    ",get_sum(x,y));
    179     }
    180 }
    View Code
  • 相关阅读:
    什么是根文件系统
    构建基本的嵌入式Linux根文件系统
    “文件系统”与“根文件系统”详解
    C#中NameValueCollection类用法详解
    别把西红柿连续种在同一块地里
    asp.net 服务器控件的 ID,ClientID,UniqueID 的区别
    不要为框架作过多的假设
    构件技术
    asp.net中控件id,clientid,uniqueid的区别
    系统架构图怎么画
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/10769453.html
Copyright © 2011-2022 走看看