zoukankan      html  css  js  c++  java
  • [bzoj 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,表示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]之间。


    My Solution

    一道可爱的树链剖分题啊

    注意区间合并和树剖中的calc即可

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 using namespace std;
      5 
      6 inline int read(){
      7     char ch;
      8     int re=0;
      9     bool flag=0;
     10     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
     11     ch=='-'?flag=1:re=ch-'0';
     12     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
     13     return flag?-re:re;
     14 }
     15 
     16 inline char rea(){
     17     char ch;
     18     while((ch=getchar())!='Q'&&ch!='C');
     19     return ch;
     20 }
     21 
     22 struct edge{
     23     int to,next;
     24     edge(int to=0,int next=0):
     25         to(to),next(next){}
     26 };
     27 
     28 struct segment{
     29     int l,r,lc,rc,sum,tag;
     30 };
     31 
     32 const int maxn=1e5+1;
     33 
     34 edge edges[maxn<<1];
     35 segment tre[maxn<<2];
     36 int n,m,cnt=1,root;
     37 //si1,si2表示query操作中取到的最高和最低颜色 
     38 int si1,si2,LL,RR;
     39 int head[maxn],data[maxn];
     40 int siz[maxn],fat[maxn],son[maxn],dep[maxn],id[maxn],id_[maxn],top[maxn];
     41 
     42 inline void add_edge(int from,int to){
     43     edges[++cnt]=edge(to,head[from]);  head[from]=cnt;
     44     edges[++cnt]=edge(from,head[to]);  head[to]=cnt;
     45 }
     46 
     47 void init(){
     48     n=read();  m=read();
     49     for(int i=1;i<=n;i++)  data[i]=read();
     50     int from,to;  cnt=0;
     51     for(int i=1;i<n;i++){
     52         from=read();  to=read();
     53         add_edge(from,to);
     54     }
     55 }
     56 
     57 void dfs_1(int x,int fa){
     58     siz[x]=1;
     59     dep[x]=dep[fa]+1;
     60     fat[x]=fa;
     61     for(int ee=head[x];ee;ee=edges[ee].next)
     62         if(edges[ee].to!=fa){
     63             dfs_1(edges[ee].to,x);
     64             siz[x]+=siz[edges[ee].to];
     65             if(!son[x]||siz[edges[ee].to]>siz[son[x]])  son[x]=edges[ee].to;
     66         }
     67 }
     68 
     69 void dfs_2(int x,int first){
     70     top[x]=first;
     71     id[x]=++cnt;
     72     id_[cnt]=x;
     73     if(!son[x])  return;
     74     dfs_2(son[x],first);
     75     for(int ee=head[x];ee;ee=edges[ee].next)
     76         if(edges[ee].to!=fat[x]&&edges[ee].to!=son[x])  dfs_2(edges[ee].to,edges[ee].to);
     77 }
     78 
     79 void push_up(int x){
     80     int lson=x<<1,rson=lson|1;
     81     tre[x].lc=tre[lson].lc;
     82     tre[x].rc=tre[rson].rc;
     83     tre[x].sum=tre[lson].sum+tre[rson].sum-(tre[lson].rc==tre[rson].lc?1:0);
     84 }
     85 
     86 void build(int x,int l,int r){
     87     tre[x].l=l;  tre[x].r=r;
     88     if(l==r){
     89         tre[x].lc=tre[x].rc=data[id_[l]];
     90         tre[x].sum=1;
     91         return;
     92     }
     93     int mid=(l+r)>>1;
     94     build(x<<1,l,mid);  build(x<<1|1,mid+1,r);
     95     push_up(x); 
     96 }
     97 
     98 void push_down(int x){
     99     int lson=x<<1,rson=lson|1;
    100     int &c=tre[x].tag;
    101     tre[lson].tag=tre[rson].tag=tre[lson].lc=
    102     tre[lson].rc=tre[rson].lc=tre[rson].rc=c;
    103     tre[lson].sum=1;  tre[rson].sum=1;
    104     c=0;
    105 }
    106 
    107 void make(){
    108     root=1;  dfs_1(root,0);
    109     cnt=0;  dfs_2(root,root);
    110     build(1,1,n);
    111 }
    112 
    113 void update(int x,int L,int R,int c){
    114     if(L<=tre[x].l&&tre[x].r<=R){
    115         tre[x].lc=tre[x].rc=tre[x].tag=c;
    116         tre[x].sum=1;
    117         return;
    118     }
    119     
    120     if(tre[x].tag)  push_down(x);
    121     
    122     int mid=(tre[x].l+tre[x].r)>>1;
    123     if(R<=mid)  update(x<<1,L,R,c);
    124     else  if(L>mid)  update(x<<1|1,L,R,c);
    125     else{
    126         update(x<<1,L,mid,c);
    127         update(x<<1|1,mid+1,R,c);
    128     }
    129     push_up(x);
    130 }
    131 
    132 int query_sum(int x,int L,int R){
    133     if(tre[x].l==LL)  si1=tre[x].lc;
    134     if(tre[x].r==RR)  si2=tre[x].rc;
    135     if(L<=tre[x].l&&tre[x].r<=R)  return tre[x].sum;
    136     
    137     if(tre[x].tag)  push_down(x);
    138     
    139     int mid=(tre[x].l+tre[x].r)>>1;
    140     if(R<=mid)  return query_sum(x<<1,L,R);
    141     if(L>mid)  return query_sum(x<<1|1,L,R);
    142     return query_sum(x<<1,L,mid)+query_sum(x<<1|1,mid+1,R)-(tre[x<<1].rc==tre[x<<1|1].lc?1:0);
    143 }
    144 
    145 void calc(int ss,int tt,int c){
    146     int f1=top[ss],f2=top[tt];
    147     while(f1!=f2){
    148         if(dep[f1]<dep[f2]){  swap(f1,f2);  swap(ss,tt);  }
    149         update(1,id[f1],id[ss],c);
    150         ss=fat[f1];  f1=top[ss];
    151     }
    152     if(dep[ss]<dep[tt])  swap(ss,tt);
    153     update(1,id[tt],id[ss],c);
    154 }
    155 
    156 int calc(int ss,int tt){
    157     int f1=top[ss],f2=top[tt],ans=0;
    158     int sid1=0,sid2=0;
    159     while(f1!=f2){
    160         if(dep[f1]<dep[f2]){  swap(f1,f2);  swap(ss,tt);  swap(sid1,sid2);  }
    161         LL=id[f1];  RR=id[ss];
    162         ans+=query_sum(1,id[f1],id[ss]);
    163         if(si2==sid1)  ans--;
    164         sid1=si1;  ss=fat[f1];  f1=top[ss];
    165     }
    166     if(dep[ss]<dep[tt])  {  swap(ss,tt);  swap(sid1,sid2);  }
    167     LL=id[tt];  RR=id[ss];
    168     ans+=query_sum(1,id[tt],id[ss]);
    169     if(sid1==si2)  ans--;
    170     if(sid2==si1)  ans--;
    171     return ans;
    172 }
    173 
    174 void solve(){
    175     char opt;
    176     int ss,tt,c;
    177     for(int i=0;i<m;i++){
    178         opt=rea();
    179         switch(opt){
    180             case 'C':{
    181                 ss=read();  tt=read();  c=read();
    182                 calc(ss,tt,c);
    183                 break;
    184             }
    185             case 'Q':{
    186                 ss=read();  tt=read();
    187                 printf("%d
    ",calc(ss,tt));
    188                 break;
    189             }
    190         }
    191     }
    192 }
    193 
    194 int main(){
    195     //freopen("data.in","r",stdin);
    196     init();
    197     make();
    198     solve();
    199     return 0;
    200 }

    それまでは 閉じこもって

    あなたも卵の中なのね

  • 相关阅读:
    Log4net 在framework Client中编译失败
    (MVC)从客户端中检测到有潜在危险的 Request.Form 值
    RichText设置高亮 (未完)
    1转换为00001等
    简单的MDX案例及说明(3)
    兼容型Word 并带传统读法
    Visual Studio 2010添加新项缺失[ADO.NET 实体数据模型]解决方法
    SQL Server 的优化方法(续转)
    两个有用的委托:Func和Action
    SQL Server 的优化方法(转)
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/6935581.html
Copyright © 2011-2022 走看看