[bzoj2243][SDOI2011]染色
2017-06-09 08:12
435 查看
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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 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
才过了几分钟,就从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; }
相关文章推荐
- 【bzoj2243】 [SDOI2011]染色 树链剖分+线段树
- bzoj2243 [SDOI2011]染色
- BZOJ 2243 [SDOI2011]染色 (树链剖分)(线段树区间修改)
- BZOJ2243 [SDOI2011]染色
- [Bzoj2243][SDOI2011]染色
- bzoj2243[SDOI2011]染色 树链剖分+线段树
- BZOJ 2243: [SDOI2011]染色 [树链剖分+细节]【数据结构】
- bzoj 2243: [SDOI2011]染色 (树链剖分+线段树)
- BZOJ 2243: [SDOI2011]染色(树剖||LCT)
- BZOJ2243 [SDOI2011]染色
- 【BZOJ2243】【SDOI2011】染色(树链剖分+线段树)
- BZOJ 2243: [SDOI2011]染色 (树链剖分,点权,线段树)
- BZOJ2243:[SDOI2011]染色
- 【BZOJ】2243 [SDOI2011]染色 树链剖分
- bzoj2243 [SDOI2011]染色
- [省选] [树链剖分] [BZOJ2243] [SDOI2011] 染色
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
- [SDOI2011]染色 BZOJ2243 树链剖分+线段树
- bzoj 2243 [SDOI2011]染色 (线段树 + 树链剖分)
- [BZOJ2243][[SDOI2011]染色][树链剖分+线段树]