ZOJ1610(区间覆盖问题+线段树)

区间覆盖问题,参考POJ2528的解法。(以下简称POJ2528为参考题)

1.对于输入数据的处理:输入和参考题不同,输入的是染色区间的端点,而参考题输入的是一段区间的编号。所以对数据进行输入的处理,处理思路为:[0,4]相当于对四段区间覆盖(也可以说染色):【0,1】,【1,2】,【2,3】,【3,4】我们根据参考题的解法对区间进行编号处理:将右端点的值作为区间的编号,这样我们的输入就可以实现端点到区间的转换。就可以根据参考题的解法来处理。处理方式:输入L,R后,将L++.

2. 使用ret数组来存储每种颜色出现的段数。

3.注意下推函数中,在下推完成后必须对当前结点的标记删除!否则一个非常重要的影响是:在线段树中考虑该节点,我们更新该节点区间下的染色时,该节点底层的染色会被该节点的颜色覆盖!

4.我们将tree[]数组的初始值考虑成一种颜色-1,遍历到底层时不能返回(将temp更新为-1)因为按照题意,不相邻的两端区间的染色(中间即使没有其他颜色)也算作一种颜色的两段。

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=8000+10;
int tree[maxn<<4];
int ret[maxn];
int n,L,R,C;
void pushdown(int rt)
{
    tree[rt<<1]=tree[rt<<1|1]=tree[rt];
    tree[rt]=-1;
}
void update(int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        tree[rt]=C;
        return;
    }
    int m=(l+r)>>1;
    if(tree[rt]!=-1)
        pushdown(rt);
    if(L<=m)
        update(l,m,rt<<1);
    if(m>1;
    query(l,m,rt<<1);
    query(m+1,r,rt<<1|1);
}
int main()
{
    while(~scanf("%d",&n))
    {
        memset(tree,-1,sizeof(tree));
        memset(ret,0,sizeof(ret));
        for(int i=0; i

 

你可能感兴趣的:(线段树)