POJ 2777 Count Color
2014-07-20 21:07
155 查看
题目大意:
现只有一个测例, 一个长度为L的长板,总共由L个相同的小段组成(1 ≤ L ≤ 100,000),小段从左到右编号为1 ~ L,现在给长板上色,规定每个小段只能涂一种颜色,刚开始时全部都涂成颜色1,假设总共有T中颜色(1 ≤ T ≤ 30),现在有O个操作(1 ≤ O ≤ 100,000),操作共有两种,一种是"C A B C",表示给编号区间[A, B]上颜色C(颜色用1 ~ T的整数表示),另一种操作是"P A B",表示要求你输出区间[A, B]之中不同颜色的总数。
题目链接
注释代码:
现只有一个测例, 一个长度为L的长板,总共由L个相同的小段组成(1 ≤ L ≤ 100,000),小段从左到右编号为1 ~ L,现在给长板上色,规定每个小段只能涂一种颜色,刚开始时全部都涂成颜色1,假设总共有T中颜色(1 ≤ T ≤ 30),现在有O个操作(1 ≤ O ≤ 100,000),操作共有两种,一种是"C A B C",表示给编号区间[A, B]上颜色C(颜色用1 ~ T的整数表示),另一种操作是"P A B",表示要求你输出区间[A, B]之中不同颜色的总数。
题目链接
注释代码:
/* * Problem ID : POJ 2777 Count Color * Author : Lirx.t.Una * Language : C * Run Time : 250 ms * Run Memory : 840 KB */ #include <stdio.h> //板的最大长度 #define MAXN 100000 #define LFT(T) ( (T) << 1 ) #define RHT(T) ( LFT(T) | 1 ) //将颜色数值转换成二进制表示方式 //颜色n就表示成二进制数第n位为1的形式 #define COLOR(C) ( 1 << ( (C) - 1 ) ) //判断一个颜色是否为纯色,纯色就只有1位有1,混色多位有1 //即检查C的二进制数是否只含一个1 #define SINGL(C) ( !( ( (C) - 1 ) & (C) ) ) //线段树,保存区间中颜色的二进制表示形式 //如果一个区间结点的颜色为0011,而其区间为[1, 5], //则表示该区间中有两种颜色,一种是颜色1,另一种是颜色2 int seg[MAXN * 3] = { 0, 1 };//根结点下标为1,因此将结点1区间都涂成颜色1 void update( int tree, int c, int ul, int ur, int lft, int rht ) { //tree结点[lft, rht]中奖区间[ul, ur]颜色涂成二进制颜色c int mid; int tl, tr;//tree_lft and tree_rht int tpc;//tmp_color,临时二进制颜色变量 //上的颜色肯定是纯色的 //如果当前结点区间已经是纯色而且和要上的色一样 //那就相当于啥事儿都没干 if ( c == seg[tree] ) return ; if ( lft == ul && ur == rht ) {//命中后区间直接上色,不呀再向下分解 seg[tree] = c; return ; } tl = LFT(tree); tr = RHT(tree); mid = ( lft + rht ) >> 1; tpc = seg[tree]; //未命中,因为命中的时候直接上色了,子结点不管情况如何都不管了,因此 //纯色结点的子结点不一定能正确反映父结点的信息,所以必须往下带 if ( SINGL(tpc) ) {//如果当前区间是纯色,需要将颜色往下带(分解) seg[tl] = tpc; seg= tpc; } if ( ur <= mid ) update( tl, c, ul, ur, lft, mid ); else if ( ul > mid ) update( tr, c, ul, ur, mid + 1, rht ); else { update( tl, c, ul, mid, lft, mid ); update( tr, c, mid + 1, ur, mid + 1, rht ); } //跟新父结点的颜色,就是两个子结点按位或,将所有颜色都集中 seg[tree] = seg[tl] | seg ; } int query( int tree, int ql, int qr, int lft, int rht ) { int mid; //如果当前结点区间(大区间)[lft, rht]已经是纯色的了则直接return不必再继续分解 //先检查纯色再检查是否命中可以省更多时间 if ( SINGL( seg[tree] ) || lft == ql && qr == rht ) return seg[tree]; mid = ( lft + rht ) >> 1; if ( qr <= mid ) return query( LFT(tree), ql, qr, lft, mid ); else if ( ql > mid ) return query( RHT(tree), ql, qr, mid + 1, rht ); else return query( LFT(tree), ql, mid, lft, mid ) | query( RHT(tree), mid + 1, qr, mid + 1, rht ); } int main() { int n, t, q;//板长,颜色数,询问数 int lft, rht, c;//c接受临时颜色(1 ~ t之间的整数) int tmp;//临时变量 int i;//计数变量 char cmd; int ans;//询问区间的不同颜色数量 scanf("%d%d%d", &n, &t, &q); while ( q-- ) { scanf("\n%c%d%d", &cmd, &lft, &rht); if ( lft > rht ) {//对于左端点大于右端点的交换端点 tmp = lft; lft = rht; rht = tmp; } switch (cmd) { case 'C' : scanf("%d",&c); update( 1, COLOR(c), lft, rht, 1, n ); break; case 'P' : ans = 0; c = query( 1, lft, rht, 1, n ); for ( i = 0; i < t; i++ )//统计二进制数中1的个数 ans += 1 & ( c >> i ); printf("%d\n", ans); break; default : break; } } return 0; }无注释代码: #include <stdio.h> #define MAXN 100000 #define LFT(T) ( (T) << 1 ) #define RHT(T) ( LFT(T) | 1 ) #define COLOR(C) ( 1 << ( (C) - 1 ) ) #define SINGL(C) ( !( ( (C) - 1 ) & (C) ) ) int seg[MAXN * 3] = { 0, 1 }; void update( int tree, int c, int ul, int ur, int lft, int rht ) { int mid; int tl, tr; int tpc; if ( c == seg[tree] ) return ; if ( lft == ul && ur == rht ) { seg[tree] = c; return ; } tl = LFT(tree); tr = RHT(tree); mid = ( lft + rht ) >> 1; tpc = seg[tree]; if ( SINGL(tpc) ) { seg[tl] = tpc; seg= tpc; } if ( ur <= mid ) update( tl, c, ul, ur, lft, mid ); else if ( ul > mid ) update( tr, c, ul, ur, mid + 1, rht ); else { update( tl, c, ul, mid, lft, mid ); update( tr, c, mid + 1, ur, mid + 1, rht ); } seg[tree] = seg[tl] | seg ; } int query( int tree, int ql, int qr, int lft, int rht ) { int mid; if ( SINGL( seg[tree] ) || lft == ql && qr == rht ) return seg[tree]; mid = ( lft + rht ) >> 1; if ( qr <= mid ) return query( LFT(tree), ql, qr, lft, mid ); else if ( ql > mid ) return query( RHT(tree), ql, qr, mid + 1, rht ); else return query( LFT(tree), ql, mid, lft, mid ) | query( RHT(tree), mid + 1, qr, mid + 1, rht ); } int main() { int n, t, q; int lft, rht, c; int tmp; int i; char cmd; int ans; scanf("%d%d%d", &n, &t, &q); while ( q-- ) { scanf("\n%c%d%d", &cmd, &lft, &rht); if ( lft > rht ) { tmp = lft; lft = rht; rht = tmp; } switch (cmd) { case 'C' : scanf("%d",&c); update( 1, COLOR(c), lft, rht, 1, n ); break; case 'P' : ans = 0; c = query( 1, lft, rht, 1, n ); for ( i = 0; i < t; i++ ) ans += 1 & ( c >> i ); printf("%d\n", ans); break; default : break; } } return 0; }单词解释:
optional:adj, 可选的,选修的相关文章推荐
- poj 2777 Count Color(线段树 区间更新)
- POJ 2777 Count Color(线段树+二进制位运算)
- POJ 2777 Count Color
- poj 2777 Count Color 线段树
- poj 2777 Count Color
- POJ 2777 Count Color (线段树区间更新)
- POJ 2777 Count Color
- POJ-2777 Count Color(线段树)
- poj 2777 Count Color(位运算+线段树区间更新 可用bitset记录)
- POJ 2777 Count Color 线段树 区间更新
- poj(2777)——Count Color(lazy思想,成段更新,区间统计)
- POJ 2777 Count Color
- POJ 2777-Count Color
- POJ 2777 Count Color (二进制或 线段树)
- POJ 2777 Count Color 【线段树 区间更新 按位或运算】
- 【线段树】 POJ 2777 Count Color
- POJ 2777 Count Color 线段树区间更新位运算
- POJ 2777-Count Color(线段树_区间染色)
- poj_2777 Count Color(线段树染色)
- POJ 2777 Count Color