栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

线段树+离散化:磁盘文件操作-CSP202112-4

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线段树+离散化:磁盘文件操作-CSP202112-4

题目描述

csp202112-4

思路分析

写这个题的时候对线段树还不是很熟,因此先写了写简单的板子题,见线段树那些事。
离散化的方法参考了100% 数据——离散化+线段树的实现。由于题目给出的修改和查询操作是预先已知的(操作本身的定义独立于程序运行状态),因此可以使用离线的离散化方法对数据进行处理,避免MLE。文章中也有动态开点线段树的方法,暂时还没有学习。

整体思路流程

首先读入并保存所有的操作,读的过程中根据操作类型保存操作涉及的区间边界坐标,注意由于切割了的区间会产生左端点-1的值和右端点+1的值,因此需要将这些坐标也保存然后执行离散化操作。离散化操作首先需要对保存的“有用坐标”进行排序(sort)、去重(unique),然后再对保存的所有操作进行映射,这里使用lower_bound执行二分查找(论熟练使用STL的重要性……)。对离散化的数据进行建树。遍历所有的操作进行线段树的区间修改、区间查询即可。 线段树有关细节

节点结构问题:本文的实现使用了如下的数据结构,相对较为简洁。

struct FILE_BLOCK {
    int l, r;
    int x;  // value: -1e9~1e9, 2e9: mixed
    int id; // id: 1~n(<2e5), 2e9: mixed
    int state;  // FREE, OCCUPIED, ZOMBIE, 2e9: mixed
};

其中:l和r存储了该节点表示的区间左右界。虽然这个界可以在递归中给出,但保存的好处是减少递归中的函数调用参数,空间换时间,实测效果非常好。x,id,state表示当前值、占用id和状态,引入了一个MIXED状态表示当前节点表示范围的某个值不唯一。需要注意在pushdown的时候只能下放不是MIXED的值。 写递归函数的时候尽量简洁,减少特判和出口情况,避免考虑不全的特判造成的错误。

比如update_test函数的递归非法状态出口条件是 fb[curr].state == OCCUPIED && fb[curr].id != MIXED,如果漏掉对 id 是否是 MIXED 的判断的话,会寄。 AC代码

#include 
#include 
#include 
#include 
using namespace std;

#define FREE 0
#define OCCUPIED 1
#define ZOMBIE 2

#define N_MAX 200005
#define MIXED 2000000020
#define FULL (-2000000020)

struct FILE_BLOCK {
    int l, r;
    int x;  // value: -1e9~1e9, 2e9: mixed
    int id; // id: 1~n(<2e5), 2e9: mixed
    int state;  // FREE, OCCUPIED, ZOMBIE, 2e9: mixed
};
struct OPRT {
    OPRT(int t, int i, int ll, int rr, int xx, int pp) : type(t), id(i), l(ll), r(rr), x(xx), p(pp) {}
    int type, id, l, r, x, p;
};

int n, m, k;
vector fb(N_MAX << 4);
vector oprt;
vector coordinates;

int discretization() {
    coordinates.push_back(0);   // let coordinates begin with 1
    sort(coordinates.begin(), coordinates.end());
    m = unique(coordinates.begin(), coordinates.end()) - coordinates.begin();   // 1~m
    coordinates.resize(m);
    for (auto & op : oprt) {
        switch (op.type) {
            case 0: case 1: case 2:
                op.l = lower_bound(coordinates.begin(), coordinates.end(), op.l) - coordinates.begin();
                op.r = lower_bound(coordinates.begin(), coordinates.end(), op.r) - coordinates.begin();
                break;
            case 3: default:
                op.p = lower_bound(coordinates.begin(), coordinates.end(), op.p) - coordinates.begin();
                break;
        }
    }
    return 0;
}

void pushup(int curr) {
    if (fb[curr<<1].id == fb[curr<<1|1].id) fb[curr].id = fb[curr<<1].id;
    else fb[curr].id = MIXED;
    if (fb[curr<<1].x == fb[curr<<1|1].x) fb[curr].x = fb[curr<<1].x;
    else fb[curr].x = MIXED;
    if (fb[curr<<1].state == fb[curr<<1|1].state) fb[curr].state = fb[curr<<1].state;
    else fb[curr].state = MIXED;
}

void build(int curr, int l, int r){
    fb[curr].l = l;
    fb[curr].r = r;
    if (l == r) return;
    else {
        int mid = l+((r-l)>>1);     // 用减法不用加法,避免爆int
        build(curr<<1, l, mid);
        build((curr<<1)+1, mid+1, r);
        pushup(curr);
    }
}
void pushdown(int curr) {
    if (fb[curr].r != fb[curr].l) {
        if(fb[curr].id != MIXED) fb[curr << 1].id = fb[curr << 1 | 1].id = fb[curr].id;
        if(fb[curr].state != MIXED) fb[curr << 1].state = fb[curr << 1 | 1].state = fb[curr].state;
        if(fb[curr].x != MIXED) fb[curr << 1].x = fb[curr << 1 | 1].x = fb[curr].x;
    }
}


int update_test(int curr, int to_l, int id) {
    if (fb[curr].state == FREE || fb[curr].state == ZOMBIE || fb[curr].id == id) return fb[curr].r;
    else if (fb[curr].state == OCCUPIED && fb[curr].id != MIXED) return FULL;   // debug: state = mixed, maybe itself
    else {  // state == mixed
        int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
        pushdown(curr);
        if (to_l <= mid) {
            int left_r = update_test(curr<<1, to_l, id);
            if (left_r < mid) return left_r;
            int right_r = update_test(curr<<1|1, to_l, id);
            return right_r == FULL ? left_r : right_r;
        }
        else {
            return update_test(curr<<1|1, to_l, id);
        }
    }
};
void update_ic(int curr, int to_l, int to_r, int x, int id) {
    if (fb[curr].l == to_l && fb[curr].r == to_r) { // 刚好覆盖
        fb[curr].state = OCCUPIED;
        fb[curr].id = id;
        fb[curr].x = x;
        return;
    }
    int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
    pushdown(curr);
    if (to_l <= mid) update_ic(curr<<1, to_l, min(to_r, mid), x, id);
    if (to_r > mid) update_ic(curr<<1|1, max(to_l, mid+1), to_r, x, id);
    pushup(curr);
};

bool deletion_test (int curr, int to_l, int to_r, int id) {
    if (fb[curr].l == to_l && fb[curr].r == to_r) { // 只在完全匹配的时候作判断
        if (fb[curr].state == OCCUPIED && fb[curr].id == id) return true;
        else return false;
    }
    int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
    pushdown(curr);
    bool avai = true;
    if (to_l <= mid) avai &= deletion_test(curr<<1, to_l, min(to_r, mid), id);
    if (to_r > mid) avai &= deletion_test(curr<<1|1, max(to_l, mid+1), to_r, id);
    return avai;
}
void deletion (int curr, int to_l, int to_r, int id) {
    if (fb[curr].l == to_l && fb[curr].r == to_r) {
        fb[curr].state = ZOMBIE;
        return;
    }
    int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
    pushdown(curr);
    if (to_l <= mid) deletion(curr<<1, to_l, min(to_r, mid), id);
    if (to_r > mid) deletion(curr<<1|1, max(to_l, mid+1), to_r, id);
    pushup(curr);
}

bool recover_test (int curr, int to_l, int to_r, int id) {
    if (fb[curr].l == to_l && fb[curr].r == to_r) {
        if (fb[curr].state == ZOMBIE && fb[curr].id == id) return true;
        else return false;
    }
    int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
    pushdown(curr);
    bool avai = true;
    if (to_l <= mid) avai &= recover_test(curr<<1, to_l, min(to_r, mid), id);
    if (to_r > mid) avai &= recover_test(curr<<1|1, max(to_l, mid+1), to_r, id);
    return avai;
}
void recover (int curr, int to_l, int to_r, int id) {
    if (fb[curr].l == to_l && fb[curr].r == to_r) {
        fb[curr].state = OCCUPIED;
        return;
    }
    int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
    pushdown(curr);
    if (to_l <= mid) recover(curr<<1, to_l, min(to_r, mid), id);
    if (to_r > mid) recover(curr<<1|1, max(to_l, mid+1), to_r, id);
    pushup(curr);
}

int query (int curr, int p) {
    if (fb[curr].l == fb[curr].r) return curr;
    else if (fb[curr].state != MIXED && fb[curr].id != MIXED && fb[curr].x != MIXED) return curr;
    else {
        int mid = fb[curr].l+((fb[curr].r-fb[curr].l)>>1);
        pushdown(curr);
        if (p <= mid) return query(curr<<1, p);
        else return query(curr<<1|1, p);
    }
}

int main() {
    scanf("%d%d%d", &n, &m, &k);
    int type=0, id=0, l=0, r=0, x=0, p=0;
    for (int i = 0; i < k; i++) {
        scanf("%d", &type);
        switch (type) {
            case 0:
                scanf("%d%d%d%d", &id, &l, &r, &x);
                oprt.emplace_back(type, id, l, r, x, 0);
                break;
            case 1:
                scanf("%d%d%d", &id, &l, &r);
                oprt.emplace_back(type, id, l, r, 0, 0);
                break;
            case 2:
                scanf("%d%d%d", &id, &l, &r);
                oprt.emplace_back(type, id, l, r, 0, 0);
                break;
            case 3:
                scanf("%d", &p);
                oprt.emplace_back(type, 0, 0, 0, 0, p);
                break;
            default:
                break;
        }
        if (type == 0 || type == 1 || type == 2) {
            coordinates.push_back(l);
            coordinates.push_back(r);
            if (l != 1) coordinates.push_back(l-1);     // 注意离散化要加入前后的点
            if (r != m) coordinates.push_back(r+1);
        }
        else {
            coordinates.push_back(p);
        }
    }
    
    discretization();
    
    build(1, 1, m-1);
    int query_index;
    for (auto & op : oprt) {
        switch (op.type) {
            case 0:
                op.r = min(op.r, update_test(1, op.l, op.id));
                if (op.r != FULL) update_ic(1, op.l, op.r, op.x, op.id);
                printf("%dn", op.r==FULL?-1:coordinates[op.r]);
                break;
            case 1:
                if (deletion_test(1, op.l, op.r, op.id)) {
                    deletion(1, op.l, op.r, op.id);
                    printf("OKn");
                }
                else {
                    printf("FAILn");
                }
                break;
            case 2:
                if (recover_test(1, op.l, op.r, op.id)) {
                    recover(1, op.l, op.r, op.id);
                    printf("OKn");
                }
                else printf("FAILn");
                break;
            case 3:
                query_index = query(1, op.p);
                if (fb[query_index].state != OCCUPIED) printf("%d %dn", 0, 0);
                else printf("%d %dn", fb[query_index].id, fb[query_index].x);
                break;
            default:
                break;
        }
    }
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/767519.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号