zoukankan      html  css  js  c++  java
  • 好题 线段树对数据的保存+离线的逆向插入 POJ 2887

    题目大意:给一个字符串,有插入和询问操作,每次往一个位置插入一个字符或者询问第p个位置的字符是什么。

    思路:我们离线询问,逆向把所有的字符都插入给线段树,然后再查询就好了,每次都要记得插入线段树的最后的位置,然后要把这个位置给保存下来在O(1)查询即可。

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    const int maxq = 2000 + 5;
    const int maxch = 1002000 + 5;
    int tree[maxch << 2];
    
    inline void pushup(int o){
        tree[o] = tree[o << 1] + tree[o << 1 | 1];
    }
    
    void buildtree(int o, int l, int r){
        if (l == r){
            tree[o] = 1;
            return ;
        }
        int mid = (l + r) / 2;
        if (l <= mid) buildtree(o << 1, l ,mid);
        if (r > mid) buildtree(o << 1 | 1, mid + 1, r);
        pushup(o);
    }
    
    void update(int o, int l, int r, int pos, int val){
        if (l == r && l == pos){
            tree[o] = val;
            return ;
        }
        int mid = (l + r) / 2;
        if (pos <= mid) update(o << 1, l, mid, pos, val);
        if (pos > mid) update(o << 1 | 1, mid + 1, r, pos, val);
        pushup(o);
    }
    
    int query(int o, int l, int r, int pos){
        if (l == r) return l;
        int mid = (l + r) / 2;
        if (tree[o << 1] >= pos) return query(o << 1, l, mid, pos);
        if (tree[o << 1] < pos) return query(o << 1 | 1, mid + 1, r, pos - tree[o << 1]);
    }
    ///要知道的东西:询问,初始的ch,线段树节点上的val,线段树该节点下还有多少子节点
    struct Query{
        int ty, pos, cnt;///表示目前有几个插入的
        char val;
        Query(int ty = 0, char val = 0, int pos = 0, int cnt = 0): ty(ty), val(val), pos(pos), cnt(cnt){}
    }q[maxch];
    int tpos[maxch], Q;
    char tval[maxch], ch[maxch];
    
    int main(){
        scanf("%s", ch);
        int len = strlen(ch);
        scanf("%d", &Q);
        int cnt = len;
        for (int i = 1; i <= Q; i++){
            char c[2]; scanf("%s", c);
            if (c[0] == 'I') {
                char cc[2]; scanf("%s", cc);
                int pos; scanf("%d", &pos);
                q[i] = Query(c[0], cc[0], pos, cnt + 1);///目前该询问下的种类,val和位置,加上已经有了多少个字母了
                cnt++;
            }
            else {
                int pos; scanf("%d", &pos);
                q[i] = Query(c[0], 0, pos, cnt);
            }
        }
        /*①逆序放入②得到逆序放入以后放入位置的val是多少*/
        int n = cnt;
        ///printf("n = %d
    ", n);
        buildtree(1, 1, n);
    
        for (int i = Q; i >= 1; i--){///知道他是在哪个位置的
            if (q[i].ty == 'I'){
                q[i].pos = min(q[i].pos, q[i].cnt);
                int p = query(1, 1, n, q[i].pos); ///线段树里面的位置
                tpos[i] = p;
                tval[p] = q[i].val;///线段树该位置下的val
                update(1, 1, n, p, 0);
            }
        }
        for (int i = 1, j = 0; i <= n; i++){
            if (tval[i] == 0){
                tval[i] = ch[j]; j++;
            }
        }
        for (int i = 1; i <= Q; i++){
            if (q[i].ty == 'I'){
                update(1, 1, n, tpos[i], 1);
            }
            else {
                int p = query(1, 1, n, q[i].pos);
                printf("%c
    ", tval[p]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    装饰器 如何理解Python装饰器?
    python装饰器详解
    window 10下安装jdk
    Linux中pam认证详解(上)
    VMware/KVM/OpenStack虚拟化之网络模式总结
    java问题排查命令
    今日面试问题
    Qwtplot3D Qt5.12.0 MinGW 编译运行
    20212022年寒假学习进度06
    Springboot笔记<10>常用注解总结
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5874522.html
Copyright © 2011-2022 走看看