poj 2528 线段树+延迟更新

题目链接:http://poj.org/problem?id=2528

题意:

    在墙上贴海报,输入n(1<=n<=10000),表示n张海报,后n行输入 两整数l,r  ( 1<= l, r<= 1e9 ),表示海报从编号为l的石头一直贴到编号为r的石头,输入顺序即为粘贴顺序。问n张贴完之后,还能看到多少张海报。

思路:

      显然区间操作,很容易联想到线段树操作,只不过区间 l,r 最大范围可达1e9,直接建树,内存必爆。   那么就需要避开1e9的数据,进行离散化,将区间变成(1到n)

      至于如何离散化,原理是映射+压缩。 

  

样例:1
5
1 4
2 6
8 10
3 4
7 10

1 4 2  6 8 10 3 4 7 10

排序+去重   :    1  2  3  4  6  7  8  10    存入x数组

对上数组进行编号  1  2  3  4  5  6  7  8     即x【1】=1    x【2】=2    x【5】=6    x【8】=10    (即对原数组进行压缩)

本题特殊的一点:需要中间插值

设一个样例

3
1 10
1 3
5 10

进行离散化:
        1    3    5    10
编号:
        1    2    3    4

依次贴海报
        1    10    对应的是  1  4
        1    3       对应的是  1    2
        5     10                   3    4

显然 依次贴【1,4】   【1,2】  【3,4】
       显然第一张海报【1,4】被覆盖,即答案为:2

但是实际答案为3。

至于如何解决:

   中间插值 (即对两个相邻数字,相差大于1的插入某值)

进行中间插值离散化:
        1  2  3   4   5   6  10
编号:
        1  2  3   4   5   6   7

这时答案为3

AC代码:

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mem0(x) memset(x,0,sizeof(x))
#define Mem1(x) memset(x,-1,sizeof(x))
#define MemX(x) memset(x,0x3f,sizeof(x))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f;
const double pi=acos(-1.0);

const int MAXN=10010;
struct Tree{
    int l,r,lazy;
}tree[MAXN<<4];

struct s{
    int l,r;
}a[MAXN<<4];
int x[MAXN<<4];
bool hash[MAXN<<4];
int n,ans;

void pushdown(int rt)
{
    tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy;
    tree[rt].lazy=-1;
}
void update(int left,int right,int c,int l,int r,int rt)
{
    if (l>=left&&r<=right){
        tree[rt].lazy=c;
        return ;
    }
    if (tree[rt].lazy!=-1)
        pushdown(rt);
    int mid=(l+r)>>1;
    if (mid>=left)
        update(left,right,c,l,mid,rt<<1);
    if (mid<right)
        update(left,right,c,mid+1,r,rt<<1|1);
    return ;
}

void query(int l,int r,int rt)
{
    if (l==r){
        if (!hash[tree[rt].lazy]){
            ans++;
            hash[tree[rt].lazy]=true;
        }
        return ;
    }
    if (tree[rt].lazy!=-1)
        pushdown(rt);
    int mid=(l+r)>>1;
    query(l,mid,rt<<1);
    query(mid+1,r,rt<<1|1);
}
int main()
{
    int n,t;
    scanf("%d",&t);
    while (t--){
        memset(tree,-1,sizeof(tree));
        memset(hash,false,sizeof(hash));
        int cnt=0;
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%d%d",&a[i].l,&a[i].r);
            x[++cnt]=a[i].l;
            x[++cnt]=a[i].r;
        }
        sort(x+1,x+cnt+1);
        int size=unique(x+1,x+cnt+1)-x-1;  //离散化+去重
        for (int i=size;i>1;i--){         //中间增值
            if (x[i]-x[i-1]>1)
                x[++size]=x[i]-1;
        }
        sort(x+1,x+size+1);
        for (int i=1;i<=n;i++){
            int l=lower_bound(x+1,x+size+1,a[i].l)-x;   //二分查找的内库函数
            int r=lower_bound(x+1,x+size+1,a[i].r)-x;
            update(l,r,i,1,size,1);
        }
        ans=0;
        query(1,size,1);
        cout<<ans<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/q1204675546/p/11279860.html

时间: 2024-11-05 17:31:04

poj 2528 线段树+延迟更新的相关文章

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

hdu 5023 线段树延迟更新+状态压缩

/* 线段树延迟更新+状态压缩 */ #include<stdio.h> #define N 1100000 struct node { int x,y,yanchi,sum; }a[N*4]; int lower[31]; void build(int t,int x,int y) { a[t].x=x; a[t].y=y; a[t].yanchi=0; if(x==y){ a[t].sum=lower[1]; return ; } int temp=t<<1; int mid=

poj 2886 线段树的更新+反素数

Who Gets the Most Candies? Time Limit: 5000 MS Memory Limit: 0 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description N children are sitting in a circle to play a game. The children are numbered from

线段树延迟更新

title: 线段树延迟更新 date: 2018-10-10 18:50:49 tags: acm 算法 categories: ACM-线段树 概述 暑假集训的时候好多东西只学了个皮毛,,,对付模板题还能试试,,,但是一看一些稍难的一些题时,,,肯定单纯的套模板是不行得了,,,那样多没意思啊,,, 延迟更新之前就看到过,,,当初的映像就是在普通的线段树里加一个lazy,,,然后可以延迟更新区间,,,这在对区间整段的更新很有用,,,因为不用对更新区间的每一个点更新,,这样就能省下很多时间,,,

Mayor&#39;s posters POJ - 2528 (线段树 + 离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 86160   Accepted: 24734 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

Mayor&#39;s posters POJ - 2528 线段树区间覆盖

//线段树区间覆盖 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=100010; int flag; struct node{ int l,r; //vis 是这块区域是否完全被覆盖 bool vis; }tr[N<<2]; struct point { int id; int x

poj 2528(线段树+离散化) 市长的海报

http://poj.org/problem?id=2528 题目大意是市长竞选要贴海报,给出墙的长度和依次张贴的海报的长度区间(参考题目给的图),问最后你能看见的海报有几张 就是有的先贴的海报可能会被后贴的海报完全盖住,那就看不见了 这里就非常抽象的区间更新,墙的长度为建立线段树的总区间,每贴一张海报代表将这个区间的颜色涂为相应的,每张海报的颜色当然 都不相同,求最后又多少种颜色就行,但这里还要用到基础的离散化 离散化是把无限空间中无限的个体映射到有限的空间中去,以此提高算法的时空效率. 简单

poj 2828(线段树单点更新)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 18561   Accepted: 9209 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue… The Lunar New Year wa

POJ 2886 线段树单点更新

转载自:http://blog.csdn.net/sdj222555/article/details/6878651 反素数拓展参照:http://blog.csdn.net/ACdreamers/article/details/25049767 题目大意就是一群熊孩子做游戏,第一个出队的人是编号为k的人.此后出队的人就是按照前一个人手里的编号.如果是正数+m就是这个人的左边的第m个人.如果是负数-m,就是 这个人的右边第m个人.由于这个人出队了.对下一个人有影响,所以+m的时候,是k+m-1.