POJ 2777 Count Color 線段樹入門題
今天開始看的線段樹,感覺樹儲存的優勢了啊,很強大、時間複雜度降低了很多啊。
在這裡先說一下題目的大體意思是:給區間進行染色,後染的顏色會會覆蓋掉之前染過的顏色,然後輸入C是代表給區間(a,b)染色成c。P代表輸出區間(a,b)一共有幾種顏色。
典型的線段樹的建立、修改、與查詢問題啊。所以要用線段樹來做啊、否則會超時的啊,我好像跑了969ms,有點龜速了啊,但是重點是學習演算法,優化以後熟悉了再說吧。
PS:這是線段樹,第一題。
Count Color
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 32820 | Accepted: 9889 |
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 divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:
1. "C A B C" Color the board from segment A to segment B with color C.
2. "P A B" Output the number of different colors painted between segment A and segment B (including).
In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.
There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:
1. "C A B C" Color the board from segment A to segment B with color C.
2. "P A B" Output the number of different colors painted between segment A and segment B (including).
In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.
Input
First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation
defined previously.
Output
Ouput results of the output operation in order, each line contains a number.
Sample Input
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
Sample Output
2 1
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-7
#define M 10001000
//#define LL __int64
#define LL long long
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
const int maxn = 100100;
using namespace std;
struct node
{
int a, b;
int color;
int ct;
} f[4*maxn];
int n, t, k;
int cnum[maxn];
int ans;
void creat(int l, int r, int num)
{
f[num].a = l;
f[num].b = r;
f[num].color = (1<<1);//初始化顏色;
f[num].ct = 0;
int mid = (l+r)/2;
if(r-l>=1)
{
creat(l, mid, 2*num);//遞迴建立線段樹;
creat(mid+1, r, 2*num+1);
}
}
void Insert(int l, int r, int c, int num)
{
int a = f[num].a;
int b = f[num].b;
if(a == l && r == b)//遞迴的出口,就是找到了這個區間;
{
f[num].color = cnum[c];
f[num].ct = c;
return;
}
int mid = (a+b)/2;
if(f[num].ct != 0)//如果根節點被染過,就用它的子節點儲存顏色,然後就把它自己的顏色去掉;
{
f[num*2].ct = f[num].ct;
f[num*2].color = f[num].color;
f[num*2+1].ct = f[num].ct;
f[num*2+1].color = f[num].color;
f[num].ct = 0;
}
if(mid >= r)
{
Insert(l, r, c, num*2);//偏左;
}
else if(mid < l)
{
Insert(l, r, c, num*2+1);//偏右;
}
else
{
Insert(l, mid, c, num*2);//中間分開的;
Insert(mid+1, r, c, num*2+1);
}
f[num].color = f[num*2].color|f[num*2+1].color;
}
void Search(int l, int r, int num)
{
int a = f[num].a;
int b = f[num].b;
int mid = (a+b)/2;
if(l <= f[num].a && f[num].b <= r)
{
ans = ans|f[num].color;//找到滿足的區間然後標記顏色;
return ;
}
else if((f[num].a <= l && r <= f[num].b) && f[num].ct != 0)
{
ans = ans|f[num].color;
return ;
}
if(mid >= r)
{
Search(l, r, num*2);
}
else if(mid < l)
{
Search(l, r, num*2+1);
}
else
{
Search(l, mid, num*2);
Search(mid+1, r, num*2+1);
}
}
int dos(int x)
{
int sum = 0;
for(int i = 1; i <= 30; i++)
{
if((x&(1 << i)) != 0)
sum ++;
}
return sum;
}
int main()
{
int i;
for(i = 1; i <= 30; i++)
cnum[i] = (1<<i);
while(cin >>n>>t>>k)
{
creat(1, n, 1);
int a, b, c;
char str;
while(k--)
{
cin >>str;
if(str == 'C')
{
cin >>a>>b>>c;
if(a > b) swap(a, b);
Insert(a, b, c, 1);
}
else if(str == 'P')
{
cin >>a>>b;
if(a > b) swap(a, b);
ans = 0;
Search(a, b, 1);
cout<<dos(ans)<<endl;
}
}
}
return 0;
}
相關文章
- POJ 2777-Count Color(線段樹-區間染色查詢)
- HDU 1556 Color the ball 線段樹入門題
- POJ 2582 Mayor's posters 線段樹入門題+離散化
- POJ 2828 Buy Tickets 線段樹入門(建樹稍微有點抽象)抽象
- 線段樹入門
- 線段樹入門理解
- 線段樹入門(Segment Tree)
- POJ 3264 Balanced Lineup 線段樹入門(點的查詢)
- HDU 1556 Color the ball(線段樹|樹狀陣列)陣列
- 線段樹模版:從入門到入墳
- HDU 1754 I Hate It 線段樹入門
- HDU 1166 敵兵佈陣 線段樹入門題目
- POJ 3468 A Simple Problem with Integers(線段樹區間操作)
- POJ 2991 Crane(線段樹+計算幾何)
- POJ 3468 A Simple Problem with Integers (線段樹 區間更新)
- POJ 3468 A Simple Problem with Integers (線段樹 區間共加)
- POJ 3468-A Simple Problem with Integers(區間更新線段樹)
- POJ 2886 Who Gets the Most Candies?(線段樹+反素數)
- 線段樹也能是 Trie 樹 題解
- 線~段~樹
- 線段樹
- POJ 2528 Mayor's posters (線段樹 區間更新+離散化)
- POJ 2528 Mayor's posters (線段樹區間更新 + 離散化)
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- POJ 3468 【區間修改+區間查詢 樹狀陣列 | 線段樹 | 分塊】陣列
- 線段樹 hate it
- 【模版】線段樹
- 01 線段樹
- 線段樹--RMQMQ
- 李超線段樹
- 線段樹模板
- 線段樹分治略解&雜題解析
- (hdu 1166)敵兵佈陣(線段樹入門,單點更新)
- POJ 3264-Balanced Lineup詳解(線段樹區間求值)
- poj 2010 Moo University - Financial Aid (貪心+線段樹)NaNAI
- 【知識點】淺入線段樹與區間最值問題
- ut.cpp 最大線段並減線段交 [線段樹]
- 線段樹筆記筆記