POJ 2777 线段树
2008-08-02 22:26
197 查看
错误原因:
1. 没有分析清楚什么时候需要向上或者先下传递颜色
2.又把seg[root].l 和 x 搞混淆了
思路:采用线段树来处理,节点的成员c用来记录颜色,采用位运算来处理,有30种颜色,二进制位从右往左数第k位表示有无颜色,那么可以用与运算 | 来合并颜色;成员same表示节点所表示区间颜色是否一样,加入same后可以在log(n)时间内实现线段树的insert和query操作。insert时要注意如果区间颜色一样,那么左右子树的颜色也一样,要在insert时传递下去
/*
PROG:
LANG: C++
ID: heben991
*/
// algorihm:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cctype>
#include <queue>
/*
#include <list>
#include <stack>
#include <set>
#include <map>
#include <cmath>
*/
using namespace std;
#define ma(a,b) (a)>(b)?(a):(b)
#define mi(a,b) (a)<(b)?(a):(b)
#define FF(i,a,b) for(int i=(a);i<=(b);i++)
#define RR(i,b) for(int i=(0);i<(b);i++)
#define clr(x) memset(x,0,sizeof(x))
#define pb push_back
#define mp make_pair
#define sz size()
#define F first
#define S second
#define vv vector
#define ii iterator
/*
#include <sstream>
#include <iterator>
#define ssm stringstream
*/
#define cn continue
#define br break
typedef int type;
const int ST = 0;
#define out(x) cout << #x << "=" << x << endl
template <class T> void show(T a, int n) { for (int i = ST; i < ST+n; i++) { cout<<a[i]<<' '; } cout<<endl; }
template <class T> void show(T a, int r, int l) { for (int i = ST; i < ST+r; i++) show(a[i], l); cout<<endl; }
const int N=110000,M=100000;
struct node
{
int l,r,c;
bool same;
};
node seg[4*N];
int l, t, o;
void build(int root, int x, int y)
{
int len=y-x+1;
int mid=(x+y)/2;
seg[root] = (node) { x,y,1,1};
if(len>1)
{
build(root*2,x,mid);
build(root*2+1,mid+1,y);
}
}
void insert(int root, int x, int y, int color)
{
int mid=(seg[root].l+seg[root].r)/2;
if(x<=seg[root].l && y>=seg[root].r)
{
seg[root].c = 1<<(color-1);
seg[root].same = 1;
}
else
{
if(seg[root].same)
{
seg[root*2].same = seg[root*2+1].same = 1;
seg[root*2].c = seg[root*2+1].c = seg[root].c;
}
if(x<=mid)insert(root*2,x,y,color);
if(y>mid)insert(root*2+1,x,y,color);
seg[root].c = seg[root*2].c | seg[root*2+1].c;
seg[root].same = 0;
}
}
/*
10 5 8
C 1 9 2
C 3 8 3
P 1 10
2
*/
int query(int root, int x, int y)
{
int mid=(seg[root].r+seg[root].l)/2;
if(seg[root].same)return seg[root].c;
if(x<=seg[root].l && y>=seg[root].r)
{
return seg[root].c;
}
{
int ls=0,rs=0;
if(x<=mid)ls = query(root*2,x,y);
if(y>mid)rs = query(root*2+1,x,y);
return ls | rs;
}
}
int count(int x)
{
int ret=0;
//printf("%x ", x);
while(x>0)
{
ret += x & 1;
x>>=1;
}
//printf("%d/n", ret);
return ret;
}
int main()
{
char s[10];
int a, b, c;
scanf("%d%d%d", &l, &t, &o);
//printf("%d %d %d/n", l, t, o);
build(1,1,M);
while(o--)
{
scanf("%s%d%d", s, &a, &b);
//printf("%s %d %d/n", s, a, b);
if(a>b) swap(a,b);
if(s[0]=='C')
{
scanf("%d", &c);
insert(1,a,b,c);
}
else
{
printf("%d/n", count(query(1,a,b)));
}
}
return 0;
}
1. 没有分析清楚什么时候需要向上或者先下传递颜色
2.又把seg[root].l 和 x 搞混淆了
思路:采用线段树来处理,节点的成员c用来记录颜色,采用位运算来处理,有30种颜色,二进制位从右往左数第k位表示有无颜色,那么可以用与运算 | 来合并颜色;成员same表示节点所表示区间颜色是否一样,加入same后可以在log(n)时间内实现线段树的insert和query操作。insert时要注意如果区间颜色一样,那么左右子树的颜色也一样,要在insert时传递下去
/*
PROG:
LANG: C++
ID: heben991
*/
// algorihm:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cctype>
#include <queue>
/*
#include <list>
#include <stack>
#include <set>
#include <map>
#include <cmath>
*/
using namespace std;
#define ma(a,b) (a)>(b)?(a):(b)
#define mi(a,b) (a)<(b)?(a):(b)
#define FF(i,a,b) for(int i=(a);i<=(b);i++)
#define RR(i,b) for(int i=(0);i<(b);i++)
#define clr(x) memset(x,0,sizeof(x))
#define pb push_back
#define mp make_pair
#define sz size()
#define F first
#define S second
#define vv vector
#define ii iterator
/*
#include <sstream>
#include <iterator>
#define ssm stringstream
*/
#define cn continue
#define br break
typedef int type;
const int ST = 0;
#define out(x) cout << #x << "=" << x << endl
template <class T> void show(T a, int n) { for (int i = ST; i < ST+n; i++) { cout<<a[i]<<' '; } cout<<endl; }
template <class T> void show(T a, int r, int l) { for (int i = ST; i < ST+r; i++) show(a[i], l); cout<<endl; }
const int N=110000,M=100000;
struct node
{
int l,r,c;
bool same;
};
node seg[4*N];
int l, t, o;
void build(int root, int x, int y)
{
int len=y-x+1;
int mid=(x+y)/2;
seg[root] = (node) { x,y,1,1};
if(len>1)
{
build(root*2,x,mid);
build(root*2+1,mid+1,y);
}
}
void insert(int root, int x, int y, int color)
{
int mid=(seg[root].l+seg[root].r)/2;
if(x<=seg[root].l && y>=seg[root].r)
{
seg[root].c = 1<<(color-1);
seg[root].same = 1;
}
else
{
if(seg[root].same)
{
seg[root*2].same = seg[root*2+1].same = 1;
seg[root*2].c = seg[root*2+1].c = seg[root].c;
}
if(x<=mid)insert(root*2,x,y,color);
if(y>mid)insert(root*2+1,x,y,color);
seg[root].c = seg[root*2].c | seg[root*2+1].c;
seg[root].same = 0;
}
}
/*
10 5 8
C 1 9 2
C 3 8 3
P 1 10
2
*/
int query(int root, int x, int y)
{
int mid=(seg[root].r+seg[root].l)/2;
if(seg[root].same)return seg[root].c;
if(x<=seg[root].l && y>=seg[root].r)
{
return seg[root].c;
}
{
int ls=0,rs=0;
if(x<=mid)ls = query(root*2,x,y);
if(y>mid)rs = query(root*2+1,x,y);
return ls | rs;
}
}
int count(int x)
{
int ret=0;
//printf("%x ", x);
while(x>0)
{
ret += x & 1;
x>>=1;
}
//printf("%d/n", ret);
return ret;
}
int main()
{
char s[10];
int a, b, c;
scanf("%d%d%d", &l, &t, &o);
//printf("%d %d %d/n", l, t, o);
build(1,1,M);
while(o--)
{
scanf("%s%d%d", s, &a, &b);
//printf("%s %d %d/n", s, a, b);
if(a>b) swap(a,b);
if(s[0]=='C')
{
scanf("%d", &c);
insert(1,a,b,c);
}
else
{
printf("%d/n", count(query(1,a,b)));
}
}
return 0;
}
相关文章推荐
- poj 2777(线段树+区间染色)
- POJ 2777 Count Color (线段树、lazy思想)
- POJ2777---线段树
- POJ2777——Count Color(线段树)
- [POJ 2777]Count Color[线段树区间更新查询]
- POJ 2777 Count Color (线段树区间更新加查询)
- 线段树模板 poj2777
- POJ 2777 Count Color(线段树+位运算)
- 线段树区间染色 浮水法 学习小记 Poj 2777 + Poj 2528
- 【线段树(lazy)】poj 2777 Count Color
- POJ-2777 Count Color(线段树,区间染色问题)
- poj 2777 线段树
- POJ 2777 Count Color(线段树区间更新)
- poj 2777 线段树 区间更新+位运算
- POJ 2777 线段树
- POJ 2777 Count Color ---线段树
- POJ 2777 Count Color(线段树)
- poj - 2777 - Count Color(线段树)
- POJ 2777 Count Color 线段树
- POJ 2777 Count Color(线段树 + 状态压缩)