Mayor's posters(线段树之点的成段更新加离散化)

bin神的萌萌哒专题

这道题目也是简单区间更新的线段树题目,不过题目的数据范围很大,直接搞,时间空间的花费都会异常的高,所以就要用到离散化来优化时间空间复杂度.

何为离散化?........................

简单地说就是对于给出的庞大数据进行一种数据上的缩小. 比如给你一段(1,10000)的区间,由于我们要的不是其区间长度,我们只需要知道这段区间的状态

如何,于是我们可以忽视其长度,把其表示成(1,2)这个区间长度极小的区间,这相当于物理上的质点. 当我们处理的问题上与其区间长度无关时,我们就可以

用到离散化.

如何离散化?.........................

举个例子,给出两段区间(1,4)(100,100000).此时应该如何离散,仔细想想可以很容易知道可以把其离散成(1,2),(3,4). 来到这里就简单明了了.把区间的两个端点

存在一个数组中,去重之后就可以对其数组元素进行标号.这样区间长度就实现了离散. 具体实现代码看下我的..................

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <cstdlib>
#include <algorithm>

#define ls u << 1
#define rs u << 1 | 1
#define lson l, mid, u << 1
#define rson mid + 1, r, u << 1 | 1
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
const int M = 2e4 + 100;
const int N = 1e7 + 100;
int tmp[M << 2],vis[M],get_hash[N],a[M];

struct Node{
    int l,r;
    void readin(){
        scanf("%d %d",&l,&r);
    }
}p[M];

void pushdown(int u){
    if(tmp[u]){
        tmp[ls] = tmp[rs] = tmp[u];
        tmp[u] = 0;
    }
}

void pushup(int u){
    if(tmp[ls] == tmp[rs]){
        tmp[u] = tmp[ls];
    }
}

void update(int L,int R,int c,int l,int r,int u){
    int mid = (l + r) >> 1;
    if(L <= l && R >= r){
        tmp[u] = c;
    }
    else {
        pushdown(u);
        if(L <= mid) update(L,R,c,lson);
        if(R > mid) update(L,R,c,rson);
        pushup(u);
    }
}

void query(int l,int r,int u){
    if(tmp[u]){
        vis[tmp[u]] = 1;
    }
    else {
        int mid = (l + r) >> 1;
        query(lson);
        query(rson);
    }
}

int main(){
    //freopen("in","r",stdin);
    int T,n,l,r;
    cin>>T;
    while(T--){
        scanf("%d",&n);
        int to = 0;
        memset(vis,0,sizeof(vis));
        memset(tmp,0,sizeof(tmp));
        for(int i = 0; i < n; i++){
            p[i].readin();
            a[to++] = p[i].l;
            a[to++] = p[i].r;
        }
        sort(a,a + to);
        to = unique(a,a + to) - a;
        for(int i = 0; i < to; i++) get_hash[a[i]] = i + 1; //离散化过程
        for(int i = 0; i < n; i++){ //离散化过程
            int l,r;
            l = get_hash[p[i].l];
            r = get_hash[p[i].r];
            update(l,r,i + 1,1,to,1);
        }
        query(1,to,1);
        int num = 0;
        for(int i = 1; i <= n; i++) if(vis[i]) num++;
        printf("%d\n",num);
    }
    return 0;
}

Mayor's posters(线段树之点的成段更新加离散化)

时间: 2025-01-07 15:00:19

Mayor's posters(线段树之点的成段更新加离散化)的相关文章

Just a Hook(线段树之点的成段更新)

萌萌哒的传送门 /* * hdu 1698 * 线段树的点的成段更新 * 这道题不用预先建树,只需把1号节点延迟标记下就行 */ #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <queue> #include <vector> #include <cstdlib>

poj 4047 Garden 线段树lazy标记与成段更新

题意: 给长度为n的序列及k(0<k<=n<=200000),m个操作p,x,y.其中(1)p==0:将x位置处的数变为y;(2)p==1:将x,y位置处的数互换.(3)p==2查询x-y位置之间连续k个数的和的最大值. 分析: 求连续区间的和最大,可以把区间看成一个点,这样这n-k+1个区间的最大和可以看做n-k+1个点的最大值,当更新原序列中位置x的值就相当于更新区间中x-k+1到x区间的值,然后用线段树做成段更新.成段更新要用到lazy标记,我的理解是:当更新或query的时候如果

线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations

题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using namespace std; #define lson l, mid, o << 1 #define rson mid + 1, r, o << 1 | 1 typedef long long ll; const int INF = 0x3f3f3f3f; const int N =

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

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

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

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

poj 2528 Mayor&#39;s posters(线段树)

题目链接:http://poj.org/problem?id=2528 思路分析:线段树处理区间覆盖问题,也可以看做每次给一段区间染不同的颜色,最后求在整段区间上含有的所有颜色种类数: 注意由于区间太大,所以需要离散化: 区间更新:对于线段树的每个结点,标记颜色,初始时没有颜色,标记为0:当更新时,使用延迟标记,需要标记传递到子节点: 区间查询:使用深度优先查询线段树,当某个子节点的颜色不为0时,即停止深度优先搜索,并在map中查询是否已经记录该段区间的颜色: 代码如下: #include <i

POJ 2528 Mayor&#39;s posters 线段树成段更新+离散化

题目来源:POJ 2528 Mayor's posters 题意:很多张海报贴在墙上 求可以看到几张海报 看那两张图就行了 第一张俯视图 思路:最多2W个不同的数 离散化一下 然后成段更新 a[rt] = i代表这个区间是第i张报纸 更新玩之后一次query cover[i]=1代表可以看到第i张报纸 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const

poj 2528 Mayor&#39;s posters 线段树区间更新

Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at al

POJ 2528 Mayor&#39;s posters(线段树,区间覆盖,单点查询)

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