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

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:

    1、将节点a到节点b路径上所有点都染成颜色c

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数nm,分别表示节点数和操作数;

    第二行包含n个正整数表示n个节点的初始颜色

    下面行每行包含两个整数xy,表示xy之间有一条无向边。

    下面行每行描述一个操作:

    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括ab)都染成颜色c

    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括ab)路径上的颜色段数量。

    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

     

     

    正解:树链剖分+线段树

    解题报告:

      链剖裸题,套个线段树。

      这题唯一难的就在于查询颜色段的时候要考虑跨越查询区间时,要记得去掉重复的部分。合并区间的时候看一下两边区间相接的部分是否是相同颜色,相同的话减掉就可以了。

      线段树维护这一段区间的左端点颜色,右端点颜色,区间不同颜色的和,记得lazy标记。

      这题AC之前WA了两发,第一发是因为没考虑颜色可以为0,第二发是因为没有对于线段树跨越区间情况去重。  

     

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 100011;
     21 int n,m,ecnt,ans;
     22 int first[MAXN],next[MAXN*2],to[MAXN*2],val[MAXN];
     23 int top[MAXN],size[MAXN],deep[MAXN],son[MAXN],id[MAXN],pre[MAXN],father[MAXN];
     24 char ch[12];
     25 int ql,qr;
     26 
     27 struct node{
     28     int l,r,lazy;
     29     int lc,rc;//左右端点的颜色
     30     int sum;
     31 }a[MAXN*4];
     32 
     33 inline int getint()
     34 {
     35        int w=0,q=0;
     36        char c=getchar();
     37        while((c<'0' || c>'9') && c!='-') c=getchar();
     38        if (c=='-')  q=1, c=getchar();
     39        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     40        return q ? -w : w;
     41 }
     42 
     43 inline void dfs1(int x,int fa){
     44     size[x]=1;
     45     for(int i=first[x];i;i=next[i]) {
     46     int v=to[i];
     47     if(v==fa)continue;
     48     deep[v]=deep[x]+1; father[v]=x;
     49     dfs1(v,x);
     50     size[x]+=size[v];if(size[v]>size[son[x]]) son[x]=v;
     51     }
     52 }
     53 
     54 inline void dfs2(int x,int fa){
     55     id[x]=++ecnt;pre[ecnt]=x;
     56     if(son[x]) top[son[x]]=top[x],dfs2(son[x],x);
     57     for(int i=first[x];i;i=next[i]) {
     58     int v=to[i];
     59     if(v==fa || v==son[x]) continue;
     60     top[v]=v; dfs2(v,x);
     61     }
     62 }
     63 
     64 inline void build(int root,int l,int r){
     65     a[root].l=l; a[root].r=r; a[root].lazy=-1;//颜色可能为0!!!
     66     if(l==r) {  a[root].sum=1; a[root].lc=a[root].rc=val[pre[l]]; return ; }
     67     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
     68     build(lc,l,mid); build(rc,mid+1,r);
     69     a[root].sum=a[lc].sum+a[rc].sum; a[root].lc=a[lc].lc; a[root].rc=a[rc].rc;
     70     if(!(a[lc].rc^a[rc].lc)) a[root].sum--;
     71 } 
     72 
     73 inline int lca(int x,int y){
     74     int f1=top[x],f2=top[y];
     75     while(f1!=f2) {
     76     if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
     77     x=father[f1]; f1=top[x];
     78     }
     79     if(deep[x]<deep[y]) swap(x,y);
     80     return y;
     81 }
     82 
     83 inline void pushdown(int root){
     84     int lin=a[root].lazy; a[root].lazy=-1;
     85     if(lin==-1 || a[root].l==a[root].r) return ;
     86     int lc=root*2,rc=lc+1;
     87     a[lc].lazy=a[rc].lazy=lin;
     88     a[root].lc=a[root].rc=a[lc].lc=a[lc].rc=a[rc].lc=a[rc].rc=lin;
     89     a[root].sum=a[lc].sum=a[rc].sum=1;
     90 }
     91 
     92 inline void update(int root){
     93     int lc=root*2,rc=lc+1;
     94     a[root].sum=a[lc].sum+a[rc].sum;   
     95     if(!(a[lc].rc^a[rc].lc)) a[root].sum--;
     96     a[root].lc=a[lc].lc; a[root].rc=a[rc].rc;
     97 }
     98 
     99 inline void query(int root,int l,int r){
    100     if(ql>qr) return ;
    101     pushdown(root);
    102     if(ql<=l && r<=qr) {
    103     ans+=a[root].sum;
    104     return ;
    105     }
    106     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
    107     if(qr<=mid) query(lc,l,mid); 
    108     else if(ql>mid) query(rc,mid+1,r); 
    109     else{//注意这里也合并一下左右!!!有可能两个端点相等
    110     query(lc,l,mid); query(rc,mid+1,r);
    111     if(a[lc].rc==a[rc].lc) ans--;
    112     }
    113 }
    114 
    115 inline void change(int root,int l,int r,int z){
    116     if(ql>qr) return ;
    117     pushdown(root);
    118     if(ql<=l && r<=qr) {
    119     a[root].lazy=z; a[root].lc=a[root].rc=a[root].lazy; a[root].sum=1; return ;
    120     }
    121     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
    122     if(ql<=mid) change(lc,l,mid,z); if(qr>mid) change(rc,mid+1,r,z);
    123     update(root);
    124 }
    125 
    126 inline int getcol(int root,int x){
    127     pushdown(root);
    128     if(a[root].l==a[root].r) return a[root].lc;
    129     int mid=(a[root].l+a[root].r)/2; int lc=root*2,rc=lc+1;
    130     if(x<=mid) return getcol(lc,x); else return getcol(rc,x);
    131 }
    132 
    133 inline void ask_change(int x,int f,int z){
    134     while(top[x]!=top[f]) {
    135     ql=id[top[x]]; qr=id[x];
    136     change(1,1,n,z);
    137     x=father[top[x]];
    138     }
    139     ql=id[f],qr=id[x],change(1,1,n,z);
    140 }
    141 
    142 inline void ask_sum(int x,int f){
    143     while(top[x]!=top[f]) {
    144     ql=id[top[x]]; qr=id[x];
    145     query(1,1,n);
    146     if(getcol(1,id[top[x]])==getcol(1,id[father[top[x]]])) ans--;//判断相接的部分是否相同,跨越轻边的时候统计一下
    147     x=father[top[x]];
    148     }
    149     ql=id[f],qr=id[x],query(1,1,n);
    150 }
    151 
    152 inline void work(){
    153     n=getint(); m=getint();
    154     for(int i=1;i<=n;i++) val[i]=getint();
    155     int x,y;
    156     for(int i=1;i<n;i++) {
    157     x=getint(); y=getint();
    158     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
    159     next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
    160     }
    161     deep[1]=1; dfs1(1,0); ecnt=0; top[1]=1; dfs2(1,0);
    162     build(1,1,n); int z,grand;
    163     while(m--) {
    164     scanf("%s",ch);
    165     if(ch[0]=='Q') {
    166         x=getint(); y=getint();
    167         grand=lca(x,y); ans=0;
    168         ask_sum(x,grand); ask_sum(y,grand);
    169         printf("%d
    ",ans-1);//不管是连续还是不同颜色都是减一即可
    170     }
    171     else{
    172         x=getint(); y=getint(); z=getint();
    173         grand=lca(x,y); 
    174         ask_change(x,grand,z); ask_change(y,grand,z);
    175     }
    176     }
    177 }
    178 
    179 int main()
    180 {
    181   work();
    182   return 0;
    183 }
  • 相关阅读:
    国税开发子系统----纳税服务子系统问题
    Hibernate中的一对一多映射和一对一映射的创建
    hibernate 创建一对一唯一外键映射的问题
    疑问,TESt中注入sessionFactory失败
    AJAX方式进行验证码的判断(JS方式)
    过滤器和拦截器的使用
    SSH框架的整合
    编码问题
    微服务架构对比
    docker安装mysql8.0连接问题,sqlyog报2058或者Navicat 1257
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5702751.html
Copyright © 2011-2022 走看看