源每一21 线段树

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

题意:就是糊墙给你一面墙让你往上粘海报 粘到最后问你能看见几张

题解:知道了线段树这个玩意之后,看到这个题,就知道他可以用线段树来做,但是它这个点的分布范围太大了,而且线段树一般都是开四倍,内存超妥妥的,这应该怎么办呢?题目给出的样例只有一万组,这样的话可以用离散化的方法来搞这个题。啥叫离散化?就是把一段大区间存储的信息用一段小区间来表示。那这个题来说,当前数组下标代表的是真实坐标的一个映射,也就是这个坐标在这一堆坐标里排什么位置。具体处理方法看代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
#define lson l,mid,fa<<1
#define rson mid+1,r,fa<<1|1
int a[100000];
int t[100000];
int ans[100000];
int laz[100000];
int coor[100000];
int f[2],num,st,ed,sum;
int se[100000];
void Add(int l,int r, int fa) {
    if(laz[fa]) {
        laz[fa<<1] = laz[fa];
        laz[fa<<1|1] = laz[fa];
        ans[fa] = laz[fa]*(r-l+1);
        laz[fa] = 0;
    }
}
void Update(int l,int r,int fa) {
    if(st<=l&&r<=ed) {laz[fa] = num; return ;}
    if(ed<l||r<st) return;
    Add(l,r,fa);
    int mid = (l+r)>>1;
    Update(lson);Update(rson);
    ans[fa] = num*(min(ed,r)-max(st,l)+1);
}
void Query(int l,int r, int fa) {
    if (l==r) {
        if(!se[ans[fa]+laz[fa]]){
            sum++;
            se[ans[fa]+laz[fa]] = 1;
        }
    return;
    }
    Add(l,r,fa);
    int mid = (l+r)>>1;
    Query(lson);Query(rson);
}
int main() {
    int c; scanf("%d",&c);
    while (c--) {
        memset(ans,0,sizeof(ans));
        memset(se,0,sizeof(se));
        int n; scanf("%d",&n);
        for (int i = 1; i <= n*2; i++) scanf("%d",&a[i]);
        for (int i = 1; i <= n*2; i++) t[i] = a[i];
        sort(t+1,t+n*2+1);
        coor[1] = t[1];
        int k = 2;
        for (int i = 2; i <= n*2; i++)
            if (t[i-1]<t[i]) coor[k++] = t[i];
        for (int i = 1; i <= n; i++) {
            for (int j = -1; j <= 0; j++) {
                int tt = a[i*2+j];
                int l = 1, r = k-1;
                while(l<=r) {
                    int mid = (l+r)>>1;
                    if(coor[mid] == tt){f[1+j] = mid; break;}
                    else if(coor[mid]<tt) l = mid+1;
                    else r = mid -1;
                }
            }
            num = i;st = f[0];ed = f[1];
            Update(1,k-1,1);
        }
        sum = 0;
        Query(1,k-1,1);
        printf("%d\n",sum);
    }
    return 0;
}

  

posted @ 2018-06-27 23:14  风语之城  阅读(75)  评论(0编辑  收藏  举报