1. 程式人生 > >[bzoj] 2243 染色

[bzoj] 2243 染色

pre n) shu amp algorithm edge mod mes algo

原題

樹鏈剖分板子題

線段樹中直接記錄染色段數,然後每個點記錄左端點顏色和右端點顏色,以便於pushup

tre[i].sum=tre[i*2].sum+tre[i*2+1].sum-(tre[i*2].rc==tre[i*2+1].lc);

然後在爬樹的過程中要單點查詢顏色,用於判斷是否-1。

線段樹不要寫跪,單點查詢要記得pushdown

#include<cstdio>
#include<algorithm>
#define N 100010
using namespace std;
int n,m,a[N],dfn[N],deep[N],head[N],tp[N],f[N],x,y,z,ref[N],son[N],size[N],cnt=1
,t; char j; struct hhh { int to,next; }edge[2*N]; struct node { int l,r,sum,lazy,lc,rc; }tre[4*N]; int read() { int ans=0,fu=1; char j=getchar(); for (;(j<‘0‘ || j>‘9‘) && j!=‘-‘;j=getchar()) ; if (j==‘-‘) fu=-1,j=getchar(); for (;j>=‘0‘ && j<=‘9‘
;j=getchar()) ans*=10,ans+=j-‘0‘; return ans*fu; } void add(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs1(int x,int fa,int dep) { f[x]=fa; deep[x]=dep+1; size[x]++; int mx=0; for (int i=head[x],v;i;i=edge[i].next) { v=edge[i].to; if
(v!=fa) { dfs1(v,x,dep+1); size[x]+=size[v]; if (size[v]>mx) mx=size[v],son[x]=v; } } } void dfs2(int x,int top) { tp[x]=top; dfn[x]=++t; ref[t]=x; if (son[x]) dfs2(son[x],top); for (int i=head[x],v;i;i=edge[i].next) { v=edge[i].to; if (v!=son[x] && v!=f[x]) dfs2(v,v); } } void build(int i,int l,int r) { tre[i].l=l; tre[i].r=r; tre[i].lazy=-1; if (l==r) { tre[i].lc=tre[i].rc=a[ref[l]]; tre[i].sum=1; return ; } int mid=(l+r)>>1; build(i*2,l,mid); build(i*2+1,mid+1,r); tre[i].lc=tre[i*2].lc; tre[i].rc=tre[i*2+1].rc; tre[i].sum=tre[i*2].sum+tre[i*2+1].sum-(tre[i*2].rc==tre[i*2+1].lc); } void push(int x) { if (tre[x].l==tre[x].r) return ; if (tre[x].lazy==-1) return ; tre[x*2].lazy=tre[x*2+1].lazy=tre[x].lazy; tre[x*2].sum=tre[x*2+1].sum=1; tre[x*2].lc=tre[x*2].rc=tre[x*2+1].lc=tre[x*2+1].rc=tre[x].lazy; tre[x].lazy=-1; } void modify(int i,int l,int r,int p) { if (l>r) swap(l,r); if (tre[i].l==l && tre[i].r==r) { tre[i].lazy=p; tre[i].sum=1; tre[i].lc=tre[i].rc=p; return ; } push(i); int mid=(tre[i].l+tre[i].r)>>1; if (l>mid) modify(i*2+1,l,r,p); else if (r<=mid) modify(i*2,l,r,p); else { modify(i*2,l,mid,p); modify(i*2+1,mid+1,r,p); } tre[i].lc=tre[i*2].lc; tre[i].rc=tre[i*2+1].rc; tre[i].sum=tre[i*2].sum+tre[i*2+1].sum-(tre[i*2].rc==tre[i*2+1].lc); } int query(int i,int l,int r) { if (l>r) swap(l,r); if (tre[i].l==l && tre[i].r==r) return tre[i].sum; push(i); int mid=(tre[i].l+tre[i].r)>>1; if (l>mid) return query(i*2+1,l,r); else if (r<=mid) return query(i*2,l,r); else return query(i*2,l,mid)+query(i*2+1,mid+1,r)-(tre[i*2].rc==tre[i*2+1].lc); } int ask(int i,int x) { if (tre[i].l==x) return tre[i].lc; if (tre[i].r==x) return tre[i].rc; push(i); int mid=(tre[i].l+tre[i].r)>>1; if (x<=mid) return ask(i*2,x); else return ask(i*2+1,x); } void pathmodify(int u,int v,int p) { while (tp[u]!=tp[v]) { if (deep[tp[u]]<deep[tp[v]]) swap(u,v); modify(1,dfn[u],dfn[tp[u]],p); u=f[tp[u]]; } modify(1,dfn[u],dfn[v],p); } int pathquery(int u,int v) { int ans=0; while (tp[u]!=tp[v]) { if (deep[tp[u]]<deep[tp[v]]) swap(u,v); ans+=query(1,dfn[u],dfn[tp[u]]); if (ask(1,dfn[tp[u]]) == ask(1,dfn[f[tp[u]]])) ans--; u=f[tp[u]]; } ans+=query(1,dfn[u],dfn[v]); return ans; } int main() { n=read(); m=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<n;i++) { x=read(); y=read(); add(x,y); add(y,x); } dfs1(1,0,0); dfs2(1,1); build(1,1,n); getchar(); while(m--) { j=getchar(); x=read(); y=read(); if (j==‘C‘) { z=read(); pathmodify(x,y,z); } else printf("%d\n",pathquery(x,y)); getchar(); } return 0; }

[bzoj] 2243 染色