POJ 2528 Mayor's posters

本文介绍了一种使用线段树进行区间更新和查询的方法,适用于处理大量区间修改与查询操作的问题。通过离散化处理端点坐标,利用递归方式建立线段树,并实现了区间覆盖更新及查询统计功能。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 20005;//不晓得为什么写成100005就过不了

struct node{
    int l,r;
    int c;
}tree[N<<2];

int l[N],r[N];
int record[N];
int ans;

struct Line{
    int point;//记录端点做点
    int num;//记录原来的编号
    bool operator < (const Line &a)const{
        return point < a.point;
    }
}line[N<<1];

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

void pushdown(int id){
    if(tree[id].c){
        tree[id<<1].c = tree[id].c;
        tree[(id<<1)|1].c = tree[id].c;
        tree[id].c = 0;
    }
}

void update(int id,int l,int r,int val){
    if(tree[id].l >= l && tree[id].r <= r){
        tree[id].c = val;
        return ;
    }
    pushdown(id);
    int mid = (tree[id].l+tree[id].r)>>1;
    if(l <= mid)
        update(id<<1,l,r,val);
    if(mid < r)
        update((id<<1)|1,l,r,val);
}

void query(int id){
    if(tree[id].c){
        if(!record[tree[id].c]){
            ans++;
            record[tree[id].c] = 1;
        }
        return ;
    }
    query(id<<1);
    query((id<<1)|1);
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i = 0; i < n; i++){
            scanf("%d%d",&l[i],&r[i]);
            line[i<<1].point = l[i];//记录数据用于离散化
            line[(i<<1)|1].point = r[i];
            line[i<<1].num = -(i+1);//线段第一个端点用负数记录
            line[(i<<1)|1].num = i+1;//线段第二个端点用正数记录
        }
        sort(line,line+2*n);
        int tmp = line[0].point;
        int cnt = 1;
        for(int i = 0; i < n*2; i++){
            if(tmp != line[i].point){ //如果当前端点和前面的端点不一样,编号值+1
                cnt++;
                tmp = line[i].point;
            }
            if(line[i].num < 0)
                l[-line[i].num-1] = cnt;
            else
                r[line[i].num-1] = cnt;
        }

        build(1,1,cnt);
        for(int i = 0; i < n; i++)
            update(1,l[i],r[i],i+1);

        memset(record,0,sizeof(record));

        ans = 0;
        query(1);
        printf("%d\n",ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值