1. 程式人生 > >B20J_2243_[SDOI2011]染色_樹鏈剖分+線段樹

B20J_2243_[SDOI2011]染色_樹鏈剖分+線段樹

線段 scanf head == 組成 樹鏈剖分 線段樹 lazy reg

B20J_2243_[SDOI2011]染色_樹鏈剖分+線段樹

一下午凈調這題了,爭取晚上多做幾道。

題意:

給定一棵有n個節點的無根樹和m個操作,操作有2類: 1、將節點a到節點b路徑上所有點都染成顏色c; 2、詢問節點a到節點b路徑上的顏色段數量(連續相同顏色被認為是同一段), 如“112221”由3段組成:“11”、“222”和“1”。 分析: 線段樹結點維護信息:區間內顏色段數t ,區間左端點顏色lco,區間右端點顏色rco,延遲標記lazy 上傳時lco[pos]=lco[lson];rco[pos]=rco[rson];t[pos]=t[lson]+t[rson];如果左區間右端點和右區間左端點顏色相同,t[pos]--; 查詢時每次找到左右端點的顏色(直接單點查找),如果LC=RC,ans--; 註意每次標記下傳的時機。 代碼
  1
#include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 #define N 1000010 6 #define M 2062145 7 #define lson pos<<1 8 #define rson pos<<1|1 9 int head[N],to[N<<1],nxt[N<<1],co[N],cnt,n,m,scc; 10 char ch[10]; 11 int
dep[N],fa[N],siz[N],son[N],top[N]; 12 int t[M],lzy[M],idx[N],lco[M],rco[M],a[N]; 13 inline void read(int &x) 14 { 15 int f=1;x=0;char s=getchar(); 16 while(s<0||s>9){if(s==-)f=-1;s=getchar();} 17 while(s>=0&&s<=9){x=(x<<3)+(x<<1)+s-0;s=getchar();}
18 x*=f; 19 } 20 inline void add(int u,int v) 21 { 22 to[++cnt]=v; 23 nxt[cnt]=head[u]; 24 head[u]=cnt; 25 } 26 inline void dfs1(int x,int y) 27 { 28 dep[x]=dep[y]+1; 29 fa[x]=y; 30 siz[x]=1; 31 for(int i=head[x];i;i=nxt[i]) 32 { 33 if(to[i]!=y) 34 { 35 dfs1(to[i],x); 36 siz[x]+=siz[to[i]]; 37 if(siz[to[i]]>siz[son[x]]) 38 { 39 son[x]=to[i]; 40 } 41 } 42 } 43 } 44 inline void dfs2(int x,int t) 45 { 46 top[x]=t; 47 idx[x]=++scc; 48 if(son[x])dfs2(son[x],t); 49 for(int i=head[x];i;i=nxt[i]) 50 { 51 if(to[i]!=fa[x]&&to[i]!=son[x]) 52 { 53 dfs2(to[i],to[i]); 54 } 55 } 56 } 57 inline void pud(int pos) 58 { 59 if(!lzy[pos])return ; 60 t[lson]=1;lzy[lson]=lco[lson]=rco[lson]=lzy[pos]; 61 t[rson]=1;lzy[rson]=lco[rson]=rco[rson]=lzy[pos]; 62 lzy[pos]=0; 63 } 64 inline void up(int l,int r,int pos,int x,int y,int c) 65 { 66 if(x<=l&&y>=r) 67 { 68 t[pos]=1; 69 lco[pos]=c; 70 rco[pos]=c; 71 lzy[pos]=c; 72 return ; 73 } 74 pud(pos); 75 int mid=l+r>>1; 76 if(x<=mid)up(l,mid,lson,x,y,c); 77 if(y>mid)up(mid+1,r,rson,x,y,c); 78 t[pos]=t[lson]+t[rson]; 79 if(lco[rson]==rco[lson])t[pos]--; 80 lco[pos]=lco[lson]; 81 rco[pos]=rco[rson]; 82 } 83 inline int query(int l,int r,int pos,int x,int y) 84 { 85 pud(pos); 86 int re=0; 87 int mid=l+r>>1; 88 if(x<=l&&y>=r) 89 { 90 return t[pos]; 91 } 92 if(y<=mid) return query(l,mid,lson,x,y); 93 else if(x>mid) return query(mid+1,r,rson,x,y); 94 else 95 { 96 re=query(l,mid,lson,x,y)+query(mid+1,r,rson,x,y); 97 if(lco[rson]==rco[lson])re--; 98 return re; 99 } 100 } 101 inline int col(int l,int r,int x,int pos) 102 { 103 pud(pos); 104 if(l==r)return lco[pos]; 105 int mid=l+r>>1; 106 if(x<=mid)return col(l,mid,x,lson); 107 else return col(mid+1,r,x,rson); 108 } 109 int main() 110 { 111 read(n),read(m); 112 int x,y,z; 113 register int i; 114 for(i=1;i<=n;++i) 115 { 116 read(a[i]); 117 } 118 for(i=1;i<n;++i) 119 { 120 read(x),read(y); 121 add(x,y); 122 add(y,x); 123 } 124 dfs1(1,0); 125 dfs2(1,1); 126 for(i=1;i<=n;++i)up(1,n,1,idx[i],idx[i],a[i]); 127 while(m--) 128 { 129 scanf("%s",ch); 130 if(ch[0]==C) 131 { 132 read(x),read(y),read(z); 133 while(top[x]!=top[y]) 134 { 135 if(dep[top[x]]>dep[top[y]])swap(x,y); 136 up(1,n,1,idx[top[y]],idx[y],z); 137 y=fa[top[y]]; 138 } 139 if(dep[x]<dep[y])swap(x,y); 140 up(1,n,1,idx[y],idx[x],z); 141 } 142 else 143 { 144 read(x),read(y); 145 int ans=0; 146 while(top[x]!=top[y]) 147 { 148 if(dep[top[x]]>dep[top[y]])swap(x,y); 149 int LC=col(1,n,idx[top[y]],1),RC=col(1,n,idx[fa[top[y]]],1); 150 ans+=query(1,n,1,idx[top[y]],idx[y]); 151 if(LC==RC)ans--; 152 y=fa[top[y]]; 153 } 154 if(dep[x]<dep[y])swap(x,y); 155 ans+=query(1,n,1,idx[y],idx[x]); 156 if(!ans)ans=1; 157 printf("%d\n",ans); 158 } 159 } 160 }

B20J_2243_[SDOI2011]染色_樹鏈剖分+線段樹