• BZOJ2243 [SDOI2011] 染色


    题目链接:http://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,表示xy之间有一条无向边。

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

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

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

    Output

    对于每个询问操作,输出一行答案。

     

    显然是树链剖分。把QQ签名改成了“Runtime Error”,结果真灵验换来了10次Runtime Error……

    不管怎样还是艰难的AC了,写了一个中午多一点点,调了一节晚自习,一个中午和一个下午放学……找出了n多bug,最严重的是把一个w<<1|1打成了w<<1,这个造成了RE

    Segment Tree的每个节点保存:这个节点所代表的区间的左端点颜色、右端点颜色、颜色段数。

    合并时如果左区间的右端点颜色等于右区间的左端点颜色就把颜色数量减1

    然后查询时如果一条轻链的两个端点颜色相同也要把结果减1

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define rep(i,l,r) for(int i=l; i<=r; i++)
      6 #define clr(x,y) memset(x,y,sizeof(x))
      7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
      8 using namespace std;
      9 const int maxn = 100010;
     10 struct Edge{
     11     Edge *pre;
     12     int to;
     13 }edge[maxn<<1];
     14 Edge *last[maxn],*pt;
     15 struct node{
     16     int l,r,c,s,lc,rc;
     17 }t[maxn<<2];
     18 int n,m,x,y,z,segnum=0,c[maxn],depth[maxn],fa[maxn],pos[maxn],size[maxn],belong[maxn];
     19 char op[10];
     20 bool vis[maxn];
     21 inline int read(){
     22     int ans = 0, f = 1;
     23     char c = getchar();
     24     while (!isdigit(c)){
     25         if (c == '-') f = -1;
     26         c = getchar();
     27     }
     28     while (isdigit(c)){
     29         ans = ans * 10 + c - '0';
     30         c = getchar();
     31     }
     32     return ans * f;
     33 }
     34 inline void addedge(int x,int y){
     35     pt->pre = last[x];
     36     pt->to = y;
     37     last[x] = pt++;
     38 }
     39 void dfs1(int x){
     40     vis[x] = 1; size[x] = 1;
     41     travel(x){
     42         if (vis[p->to]) continue;
     43         depth[p->to] = depth[x] + 1;
     44         fa[p->to] = x;
     45         dfs1(p->to);
     46         size[x] += size[p->to];
     47     }
     48 }
     49 void dfs2(int x,int chain){
     50     int k = 0; pos[x] = ++segnum; belong[x] = chain;
     51     travel(x){
     52         if (depth[p->to] > depth[x] && size[p->to] > size[k])
     53         k = p->to;
     54     }
     55     if (!k) return;
     56     dfs2(k,chain);
     57     travel(x){
     58         if (depth[p->to] > depth[x] && p->to != k) dfs2(p->to,p->to);
     59     }
     60 }
     61 inline void pushdown(int w){
     62     if (t[w].c == -1 || t[w].l == t[w].r) return;
     63     t[w<<1].s = t[w<<1|1].s = 1;
     64     t[w<<1].c = t[w<<1|1].c = t[w].c;
     65     t[w<<1].lc = t[w<<1|1].lc = t[w<<1].rc = t[w<<1|1].rc = t[w].c;
     66     t[w].c = -1;
     67 }
     68 inline void maintain(int w){
     69     t[w].lc = t[w<<1].lc; t[w].rc = t[w<<1|1].rc;
     70     t[w].s = t[w<<1].s + t[w<<1|1].s - (t[w<<1].rc == t[w<<1|1].lc);
     71 }
     72 void build(int u,int v,int w){
     73     t[w].l = u; t[w].r = v; t[w].c = -1; t[w].s = 1;
     74     if (u == v) return;
     75     int mid = (u + v) >> 1;
     76     build(u,mid,w<<1); build(mid+1,v,w<<1|1);
     77 }
     78 void change(int u,int v,int w,int x){
     79     pushdown(w);
     80     if (u == t[w].l && v == t[w].r){
     81         t[w].c = t[w].lc = t[w].rc = x; 
     82         t[w].s = 1; return;
     83     }
     84     int mid = (t[w].l + t[w].r) >> 1;
     85     if (v <= mid) change(u,v,w<<1,x);
     86     else if (u > mid) change(u,v,w<<1|1,x);
     87     else{
     88         change(u,mid,w<<1,x);
     89         change(mid+1,v,w<<1|1,x);
     90     }
     91     maintain(w);
     92 }
     93 int queryseg(int u,int v,int w){
     94     pushdown(w);
     95     if (u == t[w].l && v == t[w].r) return t[w].s;
     96     int mid = (t[w].l + t[w].r) >> 1;
     97     if (v <= mid) return queryseg(u,v,w<<1);
     98     else if (u > mid) return queryseg(u,v,w<<1|1);
     99     else{
    100         int ret = queryseg(u,mid,w<<1) + queryseg(mid+1,v,w<<1|1);
    101         if (t[w<<1].rc == t[w<<1|1].lc) ret--;
    102         return ret;
    103     }
    104 }
    105 int find(int x,int w){
    106     pushdown(w);
    107     if (t[w].l == t[w].r) return t[w].lc;
    108     int mid = (t[w].l + t[w].r) >> 1;
    109     if (x <= mid) return find(x,w<<1);
    110     else return find(x,w<<1|1);
    111 }
    112 void modify(int x,int y,int z){
    113     while (belong[x] != belong[y]){
    114         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
    115         change(pos[belong[x]],pos[x],1,z);
    116         x = fa[belong[x]];
    117     }
    118     if (depth[x] < depth[y]) swap(x,y);
    119     change(pos[y],pos[x],1,z);
    120 }
    121 int query(int x,int y){
    122     int ret = 0;
    123     while (belong[x] != belong[y]){
    124         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
    125         ret += queryseg(pos[belong[x]],pos[x],1);
    126         if (find(pos[belong[x]],1) == find(pos[fa[belong[x]]],1)) ret--;
    127         x = fa[belong[x]];
    128     }
    129     if (depth[x] < depth[y]) swap(x,y);
    130     ret += queryseg(pos[y],pos[x],1);
    131     return ret;
    132 }
    133 int main(){
    134     n = read(); m = read(); clr(last,0); pt = edge;
    135     rep(i,1,n) c[i] = read();
    136     rep(i,1,n-1){
    137         x = read(); y = read();
    138         addedge(x,y); addedge(y,x);
    139     }
    140     depth[1] = 0; dfs1(1); dfs2(1,1); build(1,n,1);
    141     rep(i,1,n) change(pos[i],pos[i],1,c[i]);
    142     rep(i,1,m){
    143         scanf("%s",op);
    144         switch(op[0]){
    145             case 'C':
    146                 x = read(); y = read(); z = read();
    147                 modify(x,y,z);
    148             break;
    149             case 'Q':
    150                 x = read(); y = read();
    151                 printf("%d
    ",query(x,y));
    152             break;
    153         }
    154     }
    155     return 0;
    156 }
    View Code
  • 相关阅读:
    LambdaExpressions(Lambda表达式)
    解密淘宝网的开源架构(转)
    使用Action、Func和Lambda表达式
    ASP.NET中进行消息处理(MSMQ) 二
    从内存变化看.NET代码执行机理(一)
    提高C#编程水平的50个要诀
    其他概念
    asp.net mvc相关开源项目
    为性能和可伸缩性做架构和设计上的Review
    你可能不知道的C#语言特性
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj2243.html
Copyright © 2020-2023  润新知