【bzoj2243】[SDOI2011]染色(树链剖分)

来源:互联网 发布:冒险岛2检测数据异常 编辑:程序博客网 时间:2024/05/26 02:20
题目:

我是超链接

题解:

这个题要维护左右端点的颜色以及中间的颜色段数

然后能说的只有各个数组的意义了

num[i]真实树中的点i在线段树最底层的编号;tree[i]线段树底层编号为i的点在真树中的编号;woc[i]底层编号为i的点在整棵线段树中的编号

最后要注意的就是数据范围了,deep啥的都是N,线段树中是4N,连边的是2N

代码:
#include <cstdio>#include <iostream> #define N 200000#define MIN -1e9using namespace std;int nxt[N*2],point[N*2],v[N*2],tot=0,cnt=0,n;int deep[N],size[N],fa[N],top[N],son[N],tree[N],num[N],totw=0;int sum[N*4],ll[N*4],rr[N*4],delta[N*4],w[N],woc[N*4+5];void addline(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;} void updata(int now){sum[now]=sum[now<<1]+sum[now<<1|1];if (rr[now<<1]==ll[now<<1|1]) sum[now]--;ll[now]=ll[now<<1];rr[now]=rr[now<<1|1];}void pushdown(int now){ if (delta[now]){delta[now<<1]=delta[now];delta[now<<1|1]=delta[now];sum[now<<1]=sum[now<<1|1]=1;ll[now<<1]=rr[now<<1]=delta[now];ll[now<<1|1]=rr[now<<1|1]=delta[now];delta[now]=0;}}void dfs_1(int now,int dep,int faa){deep[now]=dep;size[now]=1;fa[now]=faa;int maxx=MIN;for (int i=point[now];i;i=nxt[i])  if (v[i]!=faa)  {  dfs_1(v[i],dep+1,now);  size[now]+=size[v[i]];  if (size[v[i]]>maxx)  {  maxx=size[v[i]];  son[now]=v[i];}  }}void dfs_2(int now,int faa){if (son[faa]!=now) top[now]=now;else top[now]=top[faa];num[now]=++totw;if (son[now]){dfs_2(son[now],now);for (int i=point[now];i;i=nxt[i])  if (v[i]!=son[now] && v[i]!=faa)    dfs_2(v[i],now);}}void build(int now,int l,int r){if (l==r){woc[l]=now;sum[now]=1;ll[now]=rr[now]=w[tree[l]];return;}int mid=(l+r)>>1;build(now<<1,l,mid);build(now<<1|1,mid+1,r);updata(now);}                                                                                                                          void change(int now,int l,int r,int lrange,int rrange,int v){if (l>=lrange && r<=rrange){sum[now]=1;ll[now]=rr[now]=v;delta[now]=v;return;}pushdown(now);int mid=(l+r)>>1;if (mid>=lrange) change(now<<1,l,mid,lrange,rrange,v);if (mid<rrange) change(now<<1|1,mid+1,r,lrange,rrange,v);updata(now);}int qurry(int now,int l,int r,int lrange,int rrange){if (l>=lrange && r<=rrange) return sum[now];pushdown(now);int mid=(l+r)>>1,ans=0;bool qd1,qd2;qd1=false; qd2=false;if (mid>=lrange){ans+=qurry(now<<1,l,mid,lrange,rrange);qd1=true;}if (mid<rrange){ans+=qurry(now<<1|1,mid+1,r,lrange,rrange);qd2=true;}if (qd1 && qd2 && ll[now<<1|1]==rr[now<<1]) ans--;updata(now);return ans;}void work(int u,int v,int c,int id){int f1=top[u],f2=top[v],summ=0;while (f1!=f2) {if (deep[f1]<deep[f2]) {swap(f1,f2); swap(u,v);}if (id==1) change(1,1,n,num[f1],num[u],c); else{summ+=qurry(1,1,n,num[f1],num[u]);int zz=qurry(1,1,n,num[fa[f1]],num[fa[f1]]);zz=qurry(1,1,n,num[f1],num[f1]);if (ll[woc[num[f1]]]==ll[woc[num[fa[f1]]]]) summ--;}u=fa[f1]; f1=top[u];}if (num[u]>num[v]) swap(u,v);if (id==1) change(1,1,n,num[u],num[v],c);else{summ+=qurry(1,1,n,num[u],num[v]);printf("%d\n",summ);}}int main(){int m,i,x,y,u,c,vv;scanf("%d%d",&n,&m);for (i=1;i<=n;i++)  scanf("%d",&w[i]);for (i=1;i<=n-1;i++){scanf("%d%d",&x,&y);addline(x,y);}dfs_1(1,1,0);dfs_2(1,0);for (i=1;i<=n;i++) tree[num[i]]=i;build(1,1,n);for (i=1;i<=m;i++){char st[5];scanf("%s",st);if (st[0]=='C'){scanf("%d%d%d",&u,&vv,&c);work(u,vv,c,1);} else{scanf("%d%d",&u,&vv);work(u,vv,0,2);}}  }


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 泰国旅游有蚊子怎么办 啦泰国旅游拉肚子怎么办 电动车上不了牌怎么办 电动车电压低了怎么办 电车显示器不亮怎么办 电动车故障显示m怎么办 电动车上面出现m怎么办 佰仟乐购额度没有了怎么办 交易密码忘记了怎么办? 电脑打开没网怎么办 网络配适器无法运行怎么办 电脑dns没有响应怎么办 win7系统没有网上邻居怎么办 win10网络重置了怎么办 win7桌面没有网上邻居怎么办 win7电脑没有网上邻居怎么办 无线网连接受限怎么办 win7账户被锁定怎么办 贷款sdk授权失败怎么办 京东保价发票怎么办 淘宝购物出现质量问题怎么办 淘宝购物降价了怎么办 淘宝购物物流慢怎么办 在淘宝购物退货怎么办 淘宝购物未付款怎么办 淘宝购物余额不足怎么办 淘宝购物漏发货怎么办 京东618无货怎么办 iis默认文档无效怎么办? 购物卡没有磁性怎么办 墙面贴纸没有贴怎么办 车显示电池符号怎么办 遇上北京购物团怎么办 钱柜老是钱不见怎么办 写真顾客退单怎么办 电视不支持投屏怎么办 qq转错账的钱怎么办 qq关注不了别人怎么办 换货忘记要单号怎么办 快递提前签收了怎么办 签收了不明快递怎么办