给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
标签:long can center 之间 一个 its bzoj2243 odi stat
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
第一行包含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)路径上的颜色段数量。
对于每个询问操作,输出一行答案。
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
思路{
颜色段发现用树链剖分的时候记录一下区间左右端点,比较一下就可以了.
有点码.....
}
#include<bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define db double
#define N 100010
using namespace std;
int w[N];
struct ed{int nxt,to;}e[N*2];
int head[N],tot,n,m;
void LINK(int u,int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;}
void link(int u,int v){LINK(u,v),LINK(v,u);}
namespace Tree{
#define ls (o<<1)
#define rs ((o<<1)|1)
#define mid ((l+r)>>1)
int id[N],top[N],deep[N],idw[N],fa[N],sz[N],hson[N],idn;
int Sum[N*4],lc[N*4],rc[N*4],lazy[N*4];
void dfs1(int u,int faa){
deep[u]=deep[faa]+1;fa[u]=faa;sz[u]=1;
for(int i=head[u];i!=-1;i=e[i].nxt)if(e[i].to!=faa){
int v=e[i].to;dfs1(v,u);
sz[u]+=sz[v];if(sz[v]>sz[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int toop){
id[u]=++idn;idw[idn]=w[u];top[u]=toop;
if(hson[u])dfs2(hson[u],toop);
for(int i=head[u];i!=-1;i=e[i].nxt)
if(e[i].to!=hson[u]&&e[i].to!=fa[u])
dfs2(e[i].to,e[i].to);
}
void up(int o){
Sum[o]=Sum[ls]+Sum[rs];
if(rc[ls]==lc[rs])Sum[o]--;
rc[o]=rc[rs],lc[o]=lc[ls];
}
void build(int o,int l,int r){
if(l==r){Sum[o]=1,rc[o]=lc[o]=idw[l];return;}
build(rs,mid+1,r),build(ls,l,mid);
up(o);
}
void down(int o){
if(lazy[o]){
Sum[rs]=Sum[ls]=1;
rc[rs]=lc[rs]=lazy[rs]=lazy[o];
rc[ls]=lc[ls]=lazy[ls]=lazy[o];
lazy[o]=0;
}
}
void Modify(int o,int l,int r,int L,int R,int c){
if(l!=r)down(o);
if(l>=L&&r<=R){
Sum[o]=1;
rc[o]=lc[o]=lazy[o]=c;
return;
}
if(mid<L)Modify(rs,mid+1,r,L,R,c);
else if(mid>=R)Modify(ls,l,mid,L,R,c);
else Modify(rs,mid+1,r,mid,R,c),Modify(ls,l,mid,L,mid,c);
up(o);
}
int Query(int o,int l,int r,int L,int R){
if(l!=r)down(o);
if(l>=L&&r<=R)return Sum[o];
if(mid<L)return Query(rs,mid+1,r,L,R);
if(mid>=R)return Query(ls,l,mid,L,R);
else return Query(rs,mid+1,r,L,R)+Query(ls,l,mid,L,R)-(rc[ls]==lc[rs]);
}
int Querycol(int o,int l,int r,int pos){
if(l!=r)down(o);if(l==r)return rc[o];
if(mid<pos)return Querycol(rs,mid+1,r,pos);
else return Querycol(ls,l,mid,pos);
}
void work1(int x,int y,int c){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
Modify(1,1,n,id[top[x]],id[x],c);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
Modify(1,1,n,id[x],id[y],c);
}
void work2(int x,int y){
ll sum(0);
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
sum+=Query(1,1,n,id[top[x]],id[x]);
if(Querycol(1,1,n,id[top[x]])==Querycol(1,1,n,id[fa[top[x]]]))sum--;
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
sum+=Query(1,1,n,id[x],id[y]);
cout<<sum<<"\n";
}
}
char C[2];
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&w[i]);
for(int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v),link(u,v);}
Tree::dfs1(1,1),Tree::dfs2(1,1);Tree::build(1,1,n);
for(int i=1;i<=m;++i){
scanf("%s",C);
if(C[0]==‘C‘){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
Tree::work1(a,b,c);
}
else {
int a,b;scanf("%d%d",&a,&b);
Tree::work2(a,b);
}
}
return 0;
}
标签:long can center 之间 一个 its bzoj2243 odi stat
原文地址:http://www.cnblogs.com/zzmmm/p/7512980.html