bzoj 2243 树链剖分 染色
2015-06-03 23:38
405 查看
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3205 Solved: 1238
[Submit][Status][Discuss]
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;第二行包含n个正整数表示n个节点的初始颜色
下面行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。Sample Input
6 52 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
31
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。Source
第一轮day1#include <iostream> #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; //siz[v]表示以v为根的子树的节点数 //dep[v]表示v的深度(根深度为1) //top[v]表示v所在的链的顶端节点 //fa[v]表示v的父亲 //son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子) //tid[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置 const int maxn=500010; int n; int siz[maxn],dep[maxn],top[maxn],fa[maxn],son[maxn]; int tid[maxn]; int tim; int col[maxn]; int rank[maxn]; struct node { int v; int next; int w; }e[maxn*2]; int pre[maxn],cnt; void init() { cnt=0; tim=0; memset(pre,-1,sizeof(pre)); memset(son,-1,sizeof(son)); } void add(int u,int v) { e[cnt].v=v; e[cnt].next=pre[u]; pre[u]=cnt++; } //树链剖分部分 void dfs1(int u,int father,int d)//求出dep,fa,siz,son { dep[u]=d; fa[u]=father; siz[u]=1; for(int i=pre[u];i!=-1;i=e[i].next) { int v=e[i].v; if(v==father) continue; dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } void dfs2(int u,int tp) { top[u]=tp; tid[u]=++tim; rank[tim]=u; if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=pre[u];i!=-1;i=e[i].next) { int v=e[i].v; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } } //线段树部分 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int inf=1e9; int num[4*maxn]; int lc[4*maxn]; int rc[4*maxn]; int lazy[4*maxn]; void pushup(int rt) { lc[rt]=lc[rt<<1]; rc[rt]=rc[rt<<1|1]; int ans=num[rt<<1]+num[rt<<1|1]; if(rc[rt<<1]==lc[rt<<1|1]) ans--; num[rt]=ans; } void pushdown(int rt) { if(lazy[rt]) { lazy[rt<<1]=lazy[rt<<1|1]=1; num[rt<<1]=num[rt<<1|1]=1; lc[rt<<1]=rc[rt<<1]=lc[rt]; lc[rt<<1|1]=rc[rt<<1|1]=lc[rt]; lazy[rt]=0; } } void build(int l,int r,int rt) { if(l==r) { num[rt]=1; lc[rt]=col[rank[l]]; rc[rt]=col[rank[r]]; return ; } int mid=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int l,int r,int rt,int L,int R,int val) { if(L<=l&&r<=R) { lazy[rt]=1; num[rt]=1; lc[rt]=rc[rt]=val; return ; } pushdown(rt); int mid=(l+r)>>1; if(R<=mid) update(lson,L,R,val); else if(L>mid) update(rson,L,R,val); else { update(lson,L,R,val);update(rson,L,R,val); } pushup(rt); } int LC,RC; int query(int l,int r,int rt,int L,int R) { if(l==L) LC=lc[rt]; if(r==R) RC=rc[rt]; if(L<=l&&R>=r) return num[rt]; pushdown(rt); int mid=(l+r)>>1; if(R<=mid) return query(lson,L,R); else if(L>mid) return query(rson,L,R); else { int ans=query(lson,L,R)+query(rson,L,R); if(rc[rt<<1]==lc[rt<<1|1]) ans--; return ans; } } int solve(int x,int y,int id,int c) { int ans=0; if(id==1) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y);//先搜top深度大的链 update(1,n,1,tid[top[x]],tid[x],c); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); update(1,n,1,tid[x],tid[y],c); } else { int ans1=-1,ans2=-1;//记录上次链的左端的颜色 ans1与ans2分别指的两边上次链的左端颜色(接近LCA的那端的颜色) while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) {swap(x,y);swap(ans1,ans2);}//ans1始终跟着x跑 ans+=query(1,n,1,tid[top[x]],tid[x]); if(RC==ans1) ans--; ans1=LC; x=fa[top[x]]; } if(dep[x]>dep[y]){ swap(x,y);swap(ans1,ans2);}//ans1始终跟着x跑 ans+=query(1,n,1,tid[x],tid[y]); //注意:因为这里弄反了WA了无数次 if(RC==ans2) ans--; if(LC==ans1) ans--; return ans; } } int m; int main() { char op[15]; //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { init(); for(int i=1;i<=n;i++) scanf("%d",&col[i]); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs1(1,1,1); dfs2(1,1); build(1,n,1); while(m--) { char str[20]; scanf("%s",str); int u,v,c; if(str[0]=='C') { scanf("%d%d%d",&u,&v,&c); solve(u,v,1,c); } else { int u,v; scanf("%d%d",&u,&v); printf("%d\n",solve(u,v,2,0)); } } } }
相关文章推荐
- Codeforces Round #302 (Div. 2) 题解
- VMware下OS X Yosemite安装VMsvga2桌面黑屏解决方法
- 名词解释
- Java并发教程(Oracle官方资料)
- Hadoop-2.5.1集群环境搭建
- iOS图片的截取(OC)
- 西普学院Crypto之一段奇怪的代码
- IDF实验室之初探乾坤Fuck you brain
- HttpClient学习整理
- 连载《一个程序猿的生命周期》-20.7年工作感悟
- 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法
- IPMItool: IPMI 管理工具
- 高效合并两个有序数组(Merge Sorted Array)
- 连载《一个程序员的成长历程》-20.7年工作感悟
- hdu 2108 Shape of HDU【判断多边形是否是凸多边形模板】
- 设置eclipse启动时工作空间的选择对话框
- unity, 内置shader下载地址
- iOS开发—iOS多线程编程之NSThread的使用
- 斐波那契数列解析
- deeplearning.net教程使用