bzoj 2243(大学ACM恢复训练)

匿名 (未验证) 提交于 2019-12-03 00:38:01

2243: [SDOI2011]Ⱦɫ



[Submit][Status][Discuss]

Description

给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。

裸的链剖,写加调55分钟,代码能力太差。不要有畏惧心理,多写来提高。

注意把函数模块化,更新统一写

注意区间合并的先后顺序,深度小的在上,相当于左区间。链顶合并相当于左左合并,要特判。

维护左右端点颜色即可

链剖中链查询可以对每条链建线段树,应该快些,但因为线段树太丑反而更慢。

所以留坑,优化线段树。。。

  1 #include<iostream>   2 #include<cstdio>   3 #include<cstring>   4 #include<algorithm>   5 using namespace std;   6 #define maxn 100020   7    8 struct node{   9     int next,to;  10 }e[maxn * 2];  11 struct data{  12     int lc,rc,num;  13     data(){ lc = rc = num = 0; }  14     data(int a,int b,int c):lc(a),rc(b),num(c){};  15 };  16 struct node2{  17     int ls,rs,tag;  18     data dt;  19 }sgt[maxn * 20];  20 int head[maxn],cnt;  21 int n,m,col[maxn],tot,root[maxn];  22 int sz[maxn],son[maxn],fa[maxn],id[maxn],top[maxn],dth[maxn],len[maxn];  23   24 inline void adde(int x,int y){  25     e[++cnt].to = y;  26     e[cnt].next = head[x];  27     head[x] = cnt;  28 }  29 void dfs(int x){  30     sz[x] = 1;  31     for (int i = head[x] ; i ; i = e[i].next){  32         if ( e[i].to == fa[x] ) continue;  33         fa[e[i].to] = x , dth[e[i].to] = dth[x] + 1;  34         dfs(e[i].to);  35         sz[x] += sz[e[i].to];  36         if ( sz[son[x]] < sz[e[i].to] ) son[x] = e[i].to;   37     }  38 }  39 void dfs2(int x){  40     if ( son[x] ){  41         top[son[x]] = top[x] , id[son[x]] = ++len[top[x]];  42         dfs2(son[x]);  43     }  44     for (int i = head[x] ; i ; i = e[i].next){  45         if ( e[i].to == fa[x] || e[i].to == son[x] ) continue;  46         top[e[i].to] = e[i].to , id[e[i].to] = len[e[i].to] = 1;  47         dfs2(e[i].to);  48     }  49 }  50 inline data update(data dt1,data dt2){  51     data cur;  52     cur.num = dt1.num + dt2.num - (dt1.rc == dt2.lc);  53     if ( dt1.num && dt2.num ) cur.lc = dt1.lc , cur.rc = dt2.rc;  54     else if ( dt1.num ) cur.lc = dt1.lc , cur.rc = dt1.rc;  55     else if ( dt2.num ) cur.lc = dt2.lc , cur.rc = dt2.rc;  56     return cur;  57 }  58 inline void cov(int x,int c){  59     if ( !x ) return;  60     sgt[x].dt = data(c,c,1);  61     sgt[x].tag = c;  62 }  63 inline void pushdown(int x){  64     if ( sgt[x].tag != -1 ){  65         int ls = sgt[x].ls , rs = sgt[x].rs;  66         cov(ls,sgt[x].tag) , cov(rs,sgt[x].tag);  67         sgt[x].tag = -1;  68     }  69 }  70 /*inline void update(int x){  71     int ls = sgt[x].ls , rs = sgt[x].rs;  72     sgt[x].num = sgt[ls].num + sgt[rs].num - (sgt[ls].rc == sgt[rs].lc);  73     if ( ls && rs ) sgt[x].lc = sgt[ls].lc , sgt[x].rc = sgt[rs].rc;  74     else if ( ls ) sgt[x].lc = sgt[ls].lc , sgt[x].rc = sgt[ls].rc;  75     else sgt[x].lc = sgt[rs].lc , sgt[x].rc = sgt[rs].rc;  76 }*/  77 void insert(int &x,int l,int r,int id,int c){  78     if ( !x ) x = ++tot , sgt[x].tag = -1;  79     if ( l == r ){    sgt[x].dt = data(c,c,1); return; }  80     int mid = (l + r) >> 1;  81     if ( id <= mid ) insert(sgt[x].ls,l,mid,id,c);  82     else insert(sgt[x].rs,mid + 1,r,id,c);  83     sgt[x].dt = update(sgt[sgt[x].ls].dt,sgt[sgt[x].rs].dt);  84 }  85 void build(){  86     for (int i = 1 ; i <= n ; i++)  87         insert(root[top[i]],1,len[top[i]],id[i],col[i]);  88 }  89 void modify(int x,int l,int r,int ls,int rs,int c){  90     if ( !x ) return;  91     if ( ls <= l && rs >= r ){ cov(x,c); return; }  92     pushdown(x);  93     int mid = (l + r) >> 1;  94     if ( ls <= mid ) modify(sgt[x].ls,l,mid,ls,rs,c);  95     if ( rs > mid ) modify(sgt[x].rs,mid + 1,r,ls,rs,c);  96     sgt[x].dt = update(sgt[sgt[x].ls].dt,sgt[sgt[x].rs].dt);  97 }  98 data query(int x,int l,int r,int ls,int rs){  99     if ( !x ) return data(0,0,0); 100     pushdown(x); 101     if ( ls <= l && rs >= r ) return sgt[x].dt; 102     int mid = (l + r) >> 1; data dt1,dt2; 103     if ( ls <= mid ) dt1 = query(sgt[x].ls,l,mid,ls,rs); 104     if ( rs > mid ) dt2 = query(sgt[x].rs,mid + 1,r,ls,rs); 105     return update(dt1,dt2); 106 } 107 int query(int x,int y){ 108     data dt1,dt2,dt3; 109     while ( top[x] != top[y] ){ 110         if ( dth[top[x]] > dth[top[y]] ){ 111             dt1 = update(query(root[top[x]],1,len[top[x]],1,id[x]),dt1); //左边深度更小,注意合并顺序 112             x = fa[top[x]]; 113         } 114         else{ 115             dt2 = update(query(root[top[y]],1,len[top[y]],1,id[y]),dt2); 116             y = fa[top[y]]; 117         } 118     } 119     //链顶合并有特殊情况 120     if ( dth[x] < dth[y] ) 121         dt2 = update(query(root[top[x]],1,len[top[x]],id[x],id[y]),dt2); 122     else 123         dt1 = update(query(root[top[x]],1,len[top[x]],id[y],id[x]),dt1); 124     swap(dt1.lc,dt1.rc); 125     return update(dt1,dt2).num; 126 } 127 void modify(int x,int y,int c){ 128     while ( top[x] != top[y] ){ 129         if ( dth[top[x]] < dth[top[y]] ) swap(x,y); 130         modify(root[top[x]],1,len[top[x]],1,id[x],c); 131         x = fa[top[x]]; 132     } 133     if ( dth[x] < dth[y] ) modify(root[top[x]],1,len[top[x]],id[x],id[y],c); 134     else modify(root[top[x]],1,len[top[x]],id[y],id[x],c); 135 } 136 int main(){ 137     freopen("input.txt","r",stdin); 138     scanf("%d %d",&n,&m); 139     for (int i = 1 ; i <= n ; i++) scanf("%d",&col[i]); 140     for (int i = 1 ; i < n ; i++){ 141         int x,y; 142         scanf("%d %d",&x,&y); 143         adde(x,y) , adde(y,x); 144     } 145     dfs(1) , id[1] = len[1] = top[1] = 1 , dfs2(1) , build(); 146     while ( m-- ){ 147         char ch[10]; int a,b,c; 148         scanf("%s",ch); 149         if ( ch[0] == Q ){ 150             scanf("%d %d",&a,&b); 151             printf("%d\n",query(a,b)); 152         } 153         else{ 154             scanf("%d %d %d",&a,&b,&c); 155             modify(a,b,c); 156         } 157     } 158     return 0; 159 }
View Code

原文:https://www.cnblogs.com/zqq123/p/9242792.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!