【bzoj2243】[SDOI2011]染色 树链剖分 (区间合并处理)
2016-04-14 19:02
399 查看
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 5143 Solved: 1919
[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
对于每个询问操作,输出一行答案。
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
题意:
一颗树,节点各有颜色,1.修改区间颜色;2.询问区间的颜色段数;
思路:
1.区间操作--》线段树;
2.给棵树--》树剖(dfs*2 找重链,赋树剖的序);
3.询问连续区间段数:
用线段树节点维护的信息:
1.num本段区间个数;
2.l本段左端颜色;
3.r本段右端颜色;
(用于判定区间合并的处理)
*注意颜色可为0,故*lazy初始-1,或col++;
代码:
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 5143 Solved: 1919
[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
对于每个询问操作,输出一行答案。
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
题意:
一颗树,节点各有颜色,1.修改区间颜色;2.询问区间的颜色段数;
思路:
1.区间操作--》线段树;
2.给棵树--》树剖(dfs*2 找重链,赋树剖的序);
3.询问连续区间段数:
用线段树节点维护的信息:
1.num本段区间个数;
2.l本段左端颜色;
3.r本段右端颜色;
(用于判定区间合并的处理)
if(t[lson].r==t[rson].l) t[id].num--;
*注意颜色可为0,故*lazy初始-1,或col++;
代码:
#include<iostream> #include<stdio.h> #include<string.h> #include<vector> #define lson (id*2) #define rson (id*2+1) using namespace std; int n,m; struct node{ int l,r,num; int lazy; }t[800005]; vector<int> lin[100005]; int xx,yy; int a[100005],b[100005]; int in[100005],out[100005]; int size[100005]; int dep[100005]; int ans; int top[100005]; int son[100005]; int fa[100005]; int tot; void dfs1(int id,int pre)//找重链 { fa[id]=pre; size[id]=1; son[id]=-1; dep[id]=dep[pre]+1; int len=lin[id].size(); for(int i=0;i<len;i++) { if(pre==lin[id][i]) continue; dfs1(lin[id][i],id); if(son[id]==-1||size[son[id]]<size[lin[id][i]]) son[id]=lin[id][i]; size[id]+=size[lin[id][i]]; } } void dfs2(int x,int pre,int id)//赋树剖的序 { top[x]=id; in[x]=++tot; int len=lin[x].size(); if(son[x]!=-1) dfs2(son[x],x,id); for(int i=0;i<len;i++) { int v=lin[x][i]; if(v==pre||v==son[x]) continue; dfs2(v,x,v); } out[x]=tot; } void push_down(int id) { if(t[id].lazy) { t[lson].l=t[lson].r=t[rson].l=t[rson].r=t[lson].lazy=t[rson].lazy=t[id].lazy; t[lson].num=t[rson].num=1; t[id].lazy=0; } } void push_up(int id) { t[id].num=t[lson].num+t[rson].num; t[id].l=t[lson].l; t[id].r=t[rson].r; if(t[lson].r==t[rson].l) t[id].num--;//区间连接处! } void add(int id,int L,int R,int l,int r,int v) { if(l>R||r<L) return ; if(L>=l&&R<=r) { t[id].l=t[id].r=v; t[id].num=1; t[id].lazy=v; return ; } int mid=(L+R)>>1; push_down(id); add(lson,L,mid,l,r,v); add(rson,mid+1,R,l,r,v); push_up(id); } void query(int id,int L,int R,int l,int r,int ttt) { if(l>R||r<L) return ; if(L>=l&&R<=r) { if(ttt!=2) ans+=t[id].num; if(L==R) xx=t[id].l; return ; } int mid=(L+R)>>1; push_down(id); if(r<=mid) query(lson,L,mid,l,r,ttt); else if(l>mid) query(rson,mid+1,R,l,r,ttt); else { if(t[lson].r==t[rson].l) ans--;//区间连接处! query(lson,L,mid,l,r,ttt); query(rson,mid+1,R,l,r,ttt); } } void build(int id,int l,int r) { if(l==r) { t[id].num=1; t[id].l=t[id].r=b[l]; return ; } int mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); push_up(id); } int main() { int aa,bb,v; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]++; } for(int i=1;i<n;i++) { scanf("%d%d",&aa,&bb); lin[aa].push_back(bb); lin[bb].push_back(aa); } dep[1]=1; dfs1(1,0); dfs2(1,0,1); for(int i=1;i<=n;i++) b[in[i]]=a[i]; build(1,1,tot); fa[1]=1; char s[3]; for(int i=1;i<=m;i++) { scanf("%s",s); if(s[0]=='C') { scanf("%d%d%d",&aa,&bb,&v); v++; while(top[aa]!=top[bb]) { if(dep[top[aa]]<dep[top[bb]]) swap(aa,bb); add(1,1,tot,in[top[aa]],in[aa],v); aa=fa[top[aa]]; } if(dep[aa]>dep[bb]) swap(aa,bb); add(1,1,tot,in[aa],in[bb],v); } if(s[0]=='Q') { ans=0; scanf("%d%d",&aa,&bb); while(top[aa]!=top[bb]) { if(dep[top[aa]]<dep[top[bb]]) swap(aa,bb); query(1,1,tot,in[top[aa]],in[aa],1); xx=0,yy=0; query(1,1,tot,in[top[aa]],in[top[aa]],2); yy=xx; aa=fa[top[aa]]; query(1,1,tot,in[aa],in[aa],2); if(xx==yy) ans--;//区间连接处! } if(dep[aa]>dep[bb]) swap(aa,bb); query(1,1,tot,in[aa],in[bb],1); printf("%d\n",ans); } } }
相关文章推荐
- ACM-2005
- Windows下安装使用curl命令
- 网站打开慢,如何排查
- js求两者时间差
- markdown(-)简介
- 设计模式:单例和简单工厂
- ACM-2004
- How far away ?(DFS)
- MVC图解
- ACM-2003
- 【杭电】[1799]循环多少次?
- 关于加载Spring加载外部文件属性.properties的问题
- 手动实现树形结构
- com.sun.jersey.api.container.ContainerException: Exception obtaining parameters
- SGU 113 Nearly prime numbers(素数判定)
- ListView的使用(二)
- 【GDOI2016模拟3.9】暴走的图灵机
- caffe+Ubuntu14.04.10 +cuda7.0/7.5+CuDNNv4 安装
- 播放音乐提示音
- linux静态库的建立