bzoj2243 [SDOI2011]染色
2016-05-04 18:48
330 查看
树链剖分,线段树维护三个值:区间颜色数、区间左端颜色、区间右端颜色,当左区间右端颜色=右区间左端颜色时候,总颜色-1,树上的维护类似。
代码
代码
#include<cstdio> const int M = 1001010; const int N = 300010; int dp,p ,pre ,tt ,size ,f ,gf ,go ,deep ,color ; int id ,n,m,i,a,b,c,tot,e ; int l[M],r[M],lc[M],rc[M],s[M],v[M]; void link(int x,int y) { dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y; } struct O{ int ans,lc,rc; void clear() { ans=0;lc=0;rc=0; } void set(int a,int b,int c) { ans=a;lc=b;rc=c; } }; void dfs(int x,int fa) { int i=p[x]; size[x]=1; deep[x]=deep[fa]+1; while (i) { if (tt[i]!=fa) { f[tt[i]]=x; dfs(tt[i],x); if (size[tt[i]]>size[go[x]]) go[x]=tt[i]; size[x]+=size[tt[i]]; } i=pre[i]; } } void gao(int x,int Fa,int fa) { int i=p[x]; gf[x]=Fa;id[x]=++tot;e[tot]=color[x]; if (go[x]) gao(go[x],Fa,x); while (i) { if ((tt[i]!=fa)&&(tt[i]!=go[x])) gao(tt[i],tt[i],x); i=pre[i]; } } void updata(int x) { lc[x]=lc[2*x]; rc[x]=rc[2*x+1]; s[x]=s[2*x]+s[2*x+1]; if (rc[2*x]==lc[2*x+1]) s[x]--; } void build(int x,int a,int b) { int m; l[x]=a;r[x]=b;v[x]=-1; if (b-a>1) { m=(a+b)>>1; build(2*x,a,m); build(2*x+1,m,b); updata(x); } else { lc[x]=e[b]; rc[x]=e[b]; s[x]=1; } } void clean(int x) { if (v[x]>=0) { s[x]=1; lc[x]=rc[x]=v[x]; v[2*x]=v[x]; v[2*x+1]=v[x]; v[x]=-1; } } void change(int x,int a,int b,int c) { int m; clean(x); if ((a<=l[x])&&(r[x]<=b)) { v[x]=c; return; } m=(l[x]+r[x])>>1; if (a<m) change(2*x,a,b,c); if (m<b) change(2*x+1,a,b,c); clean(2*x);clean(2*x+1); updata(x); } O query(int x,int a,int b) { int m; O tmp;tmp.clear(); clean(x); if ((a<=l[x])&&(r[x]<=b)) { tmp.set(s[x],lc[x],rc[x]); return tmp; } m=(l[x]+r[x])>>1; int L=-1,R=-1,A=-1; if (a<m) { tmp=query(2*x,a,b); L=tmp.lc; R=tmp.rc; A=tmp.ans; } if (m<b) { tmp=query(2*x+1,a,b); if (L==-1) { L=tmp.lc; R=tmp.rc; A=tmp.ans; } else { A+=tmp.ans; if (R==tmp.lc) A--; R=tmp.rc; } } tmp.set(A,L,R);return tmp; } void gai(int a,int b,int c) { while (1) { if (gf[a]==gf[b]) { if (deep[a]<deep[b]) a^=b^=a^=b; change(1,id[b]-1,id[a],c); return; } else { if (deep[gf[a]]<deep[gf[b]]) a^=b^=a^=b; change(1,id[gf[a]]-1,id[a],c); a=f[gf[a]]; } } } int wen(int a,int b) { int ac=-1,bc=-1,ans=0; while (1) { if (gf[a]==gf[b]) { if (deep[a]<deep[b]) a^=b^=a^=b,ac^=bc^=ac^=bc; O tmp=query(1,id[b]-1,id[a]); ans+=tmp.ans; if (tmp.rc==ac) ans--; if (tmp.lc==bc) ans--; return ans; } else { if (deep[gf[a]]<deep[gf[b]]) a^=b^=a^=b,ac^=bc^=ac^=bc; O tmp=query(1,id[gf[a]]-1,id[a]); ans+=tmp.ans; if (tmp.rc==ac) ans--;ac=tmp.lc; a=f[gf[a]]; } } } int main() { scanf("%d%d",&n,&m); for (i=1;i<=n;i++) scanf("%d",&color[i]); for (i=1;i<n;i++) { scanf("%d%d",&a,&b); link(a,b); link(b,a); } dfs(1,0); gao(1,1,0); build(1,0,n); for (i=1;i<=m;i++) { char typ; scanf(" %c",&typ); if (typ=='Q') { scanf("%d%d",&a,&b); printf("%d\n",wen(a,b)); } else { scanf("%d%d%d",&a,&b,&c); gai(a,b,c); } } }
相关文章推荐
- Linux下文件编码转换
- SharedPreferences
- [Android] AIDL的使用情况和实例介绍
- 实现指定网段通过指定路由传输数据
- 《java入门第一季》之面向对象面试题(面向对象都做了哪些事情)
- 《java入门第一季》之面向对象面试题(面向对象都做了哪些事情)
- 分布式配置管理平台 Disconf
- 搭建ORACLE高可用 高性能 高扩展的 MMM_APE 架构
- burnside引理
- 分布式配置管理平台 Disconf
- android 利用左右滑动手势实现avtivity的跳转
- getdate.php var_dump($arry);
- 自组织特征映射SOM(Self-organizing feature Map)
- Spring @PostConstruct and @PreDestroy example
- Python-OpenCV 图像与视频处理
- 驱动编程-idt hook--中断描述符表
- grep、sed、awk
- NVIDIA JETSON 连接九轴IMU传感器(GY-85模块)
- Bagging, Boosting, and Randomization对比
- mysql主从复制的高可用解决方案