POJ2528线段树段更新逆序异或(广告牌)

题意:
     可以这样理解,有一条直线,然后用n条线段去覆盖,最后问全部都覆盖完之后还有多少是没有被完全覆盖的。


思路:

     一开始想的有点偏,想到起点排序,然后..失败了,原因是忘记了题目输入的顺序就是覆盖的顺序,后来突然想到了逆序,这个题目想到逆序也就差不多了,我们可以逆序处理,然后用异或操作去判断当前这段是否全部都被覆盖了,只要异或不是1,那么就是还有没覆盖的,那么答案++,更新这段,把这段全都覆盖上。


#include<stdio.h>
#include<string.h>
#include<algorithm>

#define N 20005
#define lson l ,mid ,t << 1
#define rson mid + 1 ,r ,t << 1 | 1

using namespace std;

typedef struct
{
    int l ,r;
}EDGE;

EDGE E[N];
int X[N*4];
int mark[N*4];
int num[N] ,numt[N];

void PushUp(int t)
{
    X[t] = X[t<<1] & X[t<<1|1];
    return ;
}

void PushDown(int t)
{
    if(mark[t])
    {
        mark[t<<1] = mark[t<<1|1] = 1;
        X[t<<1] = X[t<<1|1] = 1;
        mark[t] = 0;
    }
    return ;
}

void BuidTree()
{
    memset(X ,0 ,sizeof(X));
    memset(mark ,0 ,sizeof(mark));
    return ;
}

void Update(int l ,int r ,int t ,int a ,int b)
{
    if(a <= l && b >= r)
    {
        X[t] = mark[t] = 1;
        return ;
    }
    PushDown(t);
    int mid = (l + r) >> 1;
    if(a <= mid) Update(lson ,a ,b);
    if(b > mid) Update(rson ,a ,b);
    PushUp(t);
}

int Query(int l ,int r ,int t ,int a ,int b)
{
    if(a <= l && b >= r)
    return X[t];
    PushDown(t);
    int mid = (l + r) >> 1;
    int s1 = -1 ,s2 = -1;
    if(a <= mid) s1 = Query(lson ,a ,b);
    if(b > mid)  s2 = Query(rson ,a ,b);
    if(s1 == -1 && s2 == -1) return 0;
    if(s1 == -1) return s2;
    if(s2 == -1) return s1;
    return s1 & s2;
}

int Search2(int n ,int a)
{
    int low = 1 ,up = n ,mid ,ans;
    while(low <= up)
    {
        mid = (low + up) >> 1;
        if(a >= num[mid])
        {
            ans = mid;
            low = mid + 1;
        }
        else up = mid - 1;
    }
    return ans;
}

int main ()
{
    int n ,i ,Ans ,t ,id ,nn;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d" ,&n);
        for(id = 0 ,i = 1 ;i <= n ;i ++)
        {
            scanf("%d %d" ,&E[i].l ,&E[i].r);
            numt[++id] = E[i].l;
            numt[++id] = E[i].r;
        }
        sort(numt + 1 ,numt + id + 1);
        nn = 0;
        for(i = 1 ;i <= id ;i ++)
        if(i == 1 || numt[i] != numt[i-1])
        num[++nn] = numt[i];
        BuidTree();
        for(Ans = 0 ,i = n ;i >= 1 ;i --)
        {
            int l = Search2(nn ,E[i].l);
            int r = Search2(nn ,E[i].r);
            if(Query(1 ,nn ,1 ,l ,r)) continue;
            Ans ++;
            Update(1 ,nn ,1 ,l ,r);
        }
        printf("%d
" ,Ans);
    }
    return 0;
}







原文地址:https://www.cnblogs.com/csnd/p/12062383.html