您的位置:首页 > 其它

[bzoj2243][SDOI2011]染色

2017-06-09 08:12 435 查看

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 7722  Solved: 2899

[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 5

2 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

3

1

2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

Source

才过了几分钟,就从bzojRank1掉下来了(实际上只做了两道水题)
树链剖分+线段树维护,我只能说我是个zz,线段树根本写不动吗,只能看代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 100000 + 5;
struct Edge{
int to,next;
}e[N*4];
struct Node{
int l,r,s,c,lc,rc;
}t[N*4];
int n,m,num=0,c
,dep
,fa
,pos
,siz
,belong
,cnt,last
;
char op[10];
bool vis
;
void insert( int u, int v ){ e[++cnt].to = v; e[cnt].next = last[u]; last[u] = cnt; e[++cnt].to = u; e[cnt].next = last[v]; last[v] = cnt; }
void dfs1( int x ){
vis[x] = 1; siz[x] = 1;
for( int i = last[x]; i; i = e[i].next ){
if( vis[e[i].to] ) continue;
dep[e[i].to] = dep[x] + 1;
fa[e[i].to] = x; dfs1(e[i].to);
siz[x] += siz[e[i].to];
}
}
void dfs2( int x, int chain ){
int k = 0; pos[x] = ++num; belong[x] = chain;
for( int i = last[x]; i; i = e[i].next ) if( dep[e[i].to] > dep[x] && siz[e[i].to] > siz[k] ) k = e[i].to;
if( !k ) return ; dfs2(k,chain);
for( int i = last[x]; i; i = e[i].next ) if( dep[e[i].to] > dep[x] && e[i].to != k ) dfs2(e[i].to,e[i].to);
}
void build( int l, int r, int x ){
t[x].l = l; t[x].r = r; t[x].c = -1; t[x].s = 1;
if( l == r ) return ; int mid = ( l + r ) >> 1;
build( l, mid, x<<1 ); build( mid+1, r, x<<1|1 );
}
void pushdown( int x ){
if( t[x].c == -1 || t[x].l == t[x].r ) return ;
t[x<<1].s = t[x<<1|1].s = 1; t[x<<1].lc = t[x<<1|1].lc = t[x<<1].rc = t[x<<1|1].rc = t[x<<1].c = t[x<<1|1].c = t[x].c;
t[x].c = -1;
}
void maintain( int x ){
t[x].lc = t[x<<1].lc; t[x].rc = t[x<<1|1].rc;
t[x].s = t[x<<1].s + t[x<<1|1].s - (t[x<<1].rc == t[x<<1|1].lc);
}
void change( int l, int r, int x, int val ){
pushdown(x);
if( l == t[x].l && r == t[x].r ){ t[x].c = t[x].lc = t[x].rc = val; t[x].s = 1; return ;}
int mid = ( t[x].l + t[x].r ) >> 1;
if( r <= mid ) change( l, r, x<<1, val );
else if( l > mid ) change( l, r, x<<1|1, val );
else{
change( l, mid, x<<1, val );
change( mid+1, r, x<<1|1, val );
}
maintain(x);
}
int query( int l, int r, int x ){
pushdown(x);
if( l == t[x].l && r == t[x].r ) return t[x].s;
int mid = ( t[x].l + t[x].r ) >> 1;
if( r <= mid ) return query( l, r, x<<1 );
else if( l > mid ) return query( l, r, x<<1|1 );
else {
int ret = query( l, mid, x<<1 ) + query( mid+1, r, x<<1|1 );
if( t[x<<1].rc == t[x<<1|1].lc ) ret--; return ret;
}
}
int find( int v, int x ){
pushdown(x);
if( t[x].l == t[x].r ) return t[x].lc;
int mid = ( t[x].l + t[x].r ) >> 1;
if( v <= mid ) return find( v, x<<1 );
return find( v, x<<1|1 );
}
void modify( int l, int r, int v ){
while( belong[l] != belong[r] ){
if( dep[belong[l]] < dep[belong[r]] ) swap(l,r);
change( pos[belong[l]], pos[l], 1, v );
l = fa[belong[l]];
}
if (dep[l] < dep[r]) swap(l,r);
change( pos[r], pos[l], 1, v );
}
int query( int l, int r ){
int ret = 0;
while( belong[l] != belong[r] ){
if ( dep[belong[l]] < dep[belong[r]] ) swap(r,l);
ret += query( pos[belong[l]], pos[l], 1 );
if( find(pos[belong[l]],1) == find(pos[fa[belong[l]]],1) ) ret--;
l = fa[belong[l]];
}
if (dep[l] < dep[r]) swap(l,r);
ret += query( pos[r], pos[l], 1 );
return ret;
}
int main(){
scanf("%d%d", &n, &m);
for( int i = 1; i <= n; i++ ) scanf("%d", &c[i]);
for( int i = 1,x,y; i < n; i++ ){
scanf("%d%d", &x, &y);
insert( x, y );
}
dep[1] = 0; dfs1(1); dfs2(1,1); build(1,n,1);
for( int i = 1; i <= n; i++ ) change( pos[i], pos[i], 1, c[i] );
for( int i = 1,x,y,z; i <= m; i++ ){
scanf("%s", op);
switch(op[0]){
case 'C': scanf("%d%d%d", &x, &y, &z); modify(x,y,z); break;
case 'Q': scanf("%d%d", &x, &y); printf("%d\n", query(x,y)); break;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: