zoukankan      html  css  js  c++  java
  • 源每一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
    ",sum);
        }
        return 0;
    }
    

      

  • 相关阅读:
    IT常用英文术语解释发音
    大数据公司宣传语 公司文化企业文化
    vue 开发环境搭建,超级简单仅需3步。
    Mvc action间的传值
    获取文件路径
    WebStorm注册码
    webstrom快捷键
    Nuget-使用图形化界面打包自己的类库
    使用StyleCop进行代码审查
    InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET程序)
  • 原文地址:https://www.cnblogs.com/fengyuzhicheng/p/9236523.html
Copyright © 2011-2022 走看看