POJ2777 Count Color 线段树区间更新

题目描述:

长度为L个单位的画板,有T种不同的颜料,现要求按序做O个操作,操作分两种:

1.“C A B C”,即将A到B之间的区域涂上颜色C

2.“P A B”,查询[A,B]区域内出现的颜色种类

出现操作2时,请输出答案

PS:初始状态下画板颜色为1

一开始没有想那么好,用int整型位移来代替颜色,还是使用了最传统的bool color[来记录,可是不知道错在了哪里,

#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>

#define ll long long

#define LL __int64

#define eps 1e-8

#define inf 0xfffffff

//const LL INF = 1LL<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;

const int N = 100000 + 5;

typedef struct Node {
	int color;
	int l,r;
};

Node tree[N * 4];
bool vis[50];

void init() {
	memset(vis,false,sizeof(vis));
}

void build(int l,int r,int id) {
	tree[id].color = 1;
	tree[id].l = l;
	tree[id].r = r;
	if(tree[id].l == tree[id].r)return;
	int mid = (l + r)/2;
	build(l,mid,id<<1);
	build(mid + 1,r,id<<1|1);
}

void update(int l,int r,int id,int color) {
	if(tree[id].l >= l && tree[id].r <= r) {
		tree[id].color = color;return;
	}
	int mid = (tree[id].l + tree[id].r)/2;
	tree[id].color = -1;
	if(r <= mid) update(l,r,id<<1,color);
	else  {
		if(l > mid)update(l,r,id<<1|1,color);
		else {
			update(l,mid,id<<1,color);
			update(mid+1,r,id<<1|1,color);
		}
	}
}

void update2(int l,int r,int id) {
	if(tree[id].color > 0) {
		vis[tree[id].color] = true;return;
	}
	if(tree[id].l == tree[id].r)return;
	int mid = (tree[id].l + tree[id].r)/2;
	if(r <= mid) update2(l,r,id<<1);
	else {
		if(l > mid)update2(l,r,id<<1|1);
		else {
			update2(l,mid,id<<1);
			update2(mid+1,r,id<<1|1);
		}
	}
}

int find(int x) {
	int ans = 0;
	for(int i=1;i<=x;i++)
		if(vis[i])
			ans++;
	return ans;
}

int main() {
	int n,m,q;
	while(scanf("%d %d %d",&n,&m,&q) == 3 ){
		memset(tree,0,sizeof(tree));
		init();
		build(1,n,1);
		while(q--) {
			char s[2];
			scanf("%s",s);
			if(s[0] == 'C') {
				int x,y,c;
				scanf("%d %d %d",&x,&y,&c);
				if(x > y)swap(x,y);
				update(x,y,1,c);
			}
			else {
				int x,y;
				scanf("%d %d",&x,&y);
				init();
				if(x > y)swap(x,y);
				update2(x,y,1);
				printf("%d\n",find(m));
			}

		}
	}
	return 0;
}

后来看了别人的一下,看到方法不一样,跑了案例也没发现自己的错误,继续检查还是不行,难道真的是方法不行?换了个方法过了,但是上面的代码错误原因还是没有查出来,WA哭

#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>

#define ll long long

#define LL __int64

#define eps 1e-8

#define inf 0xfffffff

//const LL INF = 1LL<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;

const int N = 100000 + 5;

typedef struct Node {
	int l,r;
	int color;
	int flag;
};

Node tree[N * 4];

void init() {
	memset(tree,0,sizeof(tree));
}

void cal(int id) {
	tree[id].color = tree[id<<1].color | tree[id<<1|1].color;
}

void build(int l,int r,int id) {
	tree[id].l = l;
	tree[id].r = r;
	tree[id].color = 1;
	tree[id].flag = 1;
	if(tree[id].l == tree[id].r) return;
	int mid = (l + r)/2;
	build(l,mid,id<<1);
	build(mid+1,r,id<<1|1);
}

void cover(int id) {
	tree[id<<1].color = tree[id].color;
	tree[id<<1].flag = 1;
	tree[id<<1|1].color = tree[id].color;
	tree[id<<1|1].flag = 1;
	tree[id].flag = 0;
}

void updata(int l,int r,int id,int col) {
	if(l <= tree[id].l && r >= tree[id].r) {
		tree[id].color = col;
		tree[id].flag = 1;
		return;
	}
	if(tree[id].color == col)return;
	if(tree[id].flag)cover(id);
	int mid = (tree[id].l + tree[id].r)/2;
	if(r <= mid) updata(l,r,id<<1,col);
	else if(l > mid)updata(l,r,id<<1|1,col);
	else {
		updata(l,mid,id<<1,col);
		updata(mid+1,r,id<<1|1,col);
	}
	cal(id);
}

int ans;

void query(int l,int r,int id) {
	if(l <= tree[id].l && r >= tree[id].r) {
		ans |= tree[id].color;return;
	}
	if(tree[id].flag) {
		ans |= tree[id].color;return;
	}
	int mid = (tree[id].l + tree[id].r)/2;
	if(r <= mid) query(l,r,id<<1);
	else if(l > mid) query(l,r,id<<1|1);
	else {
		query(l,mid,id<<1);
		query(mid+1,r,id<<1|1);
	}
}

int main() {
	int n,m,q;
	while(scanf("%d %d %d",&n,&m,&q) == 3) {
		init();
		build(1,n,1);
		char s[2];
		while(q--) {
			scanf("%s",s);
			if(s[0] == 'C') {
				int x,y,c;
				scanf("%d %d %d",&x,&y,&c);
				if(x > y)swap(x,y);
				updata(x,y,1,1<<(c-1));//把颜色改成用正向委员算表示
			}
			else {
				int x,y;
				scanf("%d %d",&x,&y);
				if(x > y)swap(x,y);
				ans = 0;
				query(x,y,1);
				int cnt = 0;
				while(ans) {
					if(ans%2)cnt++;
					ans /= 2;
				}
				printf("%d\n",cnt);
			}
		}
	}
	return 0;
}

POJ2777 Count Color 线段树区间更新

时间: 2024-08-17 19:08:49

POJ2777 Count Color 线段树区间更新的相关文章

Count Color (线段树区间染色?二进制状态压缩)

题目链接:https://vjudge.net/problem/POJ-2777 题意: 有L个画板,30种颜色,o个操作:P a b :询问a-b 种有多少种颜色不同的,C  a b c:把a-b全部涂成c的颜色(覆盖掉) 1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #in

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

PKU 2777 Count Color (线段树区间更新)

题意: 给你三个数:L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000),表示有一长度为L的板(1~L), 有T种颜色(1~T),然后有O个操作,初始板1~L的颜色为1,"C A B C"表示在区间A,B图上C颜色, "P A B" 表示询问 A,B区间有几种不同的颜色. #include <stdio.h> #include <iostr

poj 2777 Count Color (线段树区间更新)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37647   Accepted: 11315 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

非结构体线段树版 ZJU 1610 Count the Colors (线段树区间更新)

Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can see at last. Input The first line of each data set contains exactly

hdu1556 Color the ball(线段树区间更新)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 12814    Accepted Submission(s): 6401 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"

ZOJ 1610 Count the Colors (线段树区间更新)

题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头输出. //ZOJ 1610 #include <cstdio> #include <cstring> #include <iostream> using namespace std ; int p[8010*4],lz[8010*4] ,hashh[8010*4],has

ZOJ - 1610 Count the Colors(线段树区间更新,单点查询)

1.给了每条线段的颜色,存在颜色覆盖,求表面上能够看到的颜色种类以及每种颜色的段数. 2.线段树区间更新,单点查询. 但是有点细节,比如: 输入: 2 0 1 1 2 3 1 输出: 1 2 这种情况就需要处理一下,代码中把所有的左端点都+1,避免了这种情况. 3. #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define L(root) ((root) &l

POJ 2777 Count Color (线段树+位运算)

题意很简单了,对一个区间有两种操作: 1. "C A B C" Color the board from segment A to segment B with color C. //A~B涂上颜色C 2. "P A B" Output the number of different colors painted between segment A and segment B (including). //输出A~B间颜色的种类数 题目链接:http://poj.o