zoukankan      html  css  js  c++  java
  • 维护后面的position sg函数概念,离线+线段 bzoj 3339

    3339: Rmq Problem

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 1160  Solved: 596
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input

    7 5
    0 2 1 0 1 3 2
    1 3
    2 3
    1 4
    3 6
    2 7

    Sample Output

    3
    0
    3
    2
    4

    HINT

    Source

    http://www.lydsy.com/JudgeOnline/problem.php?id=3339

    思路:

    首先,我们预处理处[1,i]区间中的mex函数,即mex[i]为(1~i)中没有出现过的数字。

    然后对于区间的移动,从[l,r]->[l+1,r],我们定义next[l]表示下一次a[l]出现的位置。然后我们发现,如果next[l] >= r,那么区间[l,r]和[l+1,r]的sg函数是不一样的,所以,我们对于[ l+1,next[l]-1 ]区间进行修改操作,对mex取min的就好了。然后这步操作是区间操作,我们用线段树来解决就行。

    然后我们开始从左到右暴力一遍,并且通过线段树来维护,lazy一下即可。

    这题最关键的部分就是在于询问部分!

    因为询问的话是询问一个区间[l,r]的,但是我们只需要询问第r个位置的mex的值是多少就好了。(因为线段树更新以后的[l+1, next[l] - 1 ]会对区间最小造成干扰,所以我们只需要知道在L之前,有没有一个区间能更新到R即可,所以就只需要查询R这个点)

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #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
    #define haha printf("haha
    ")
    const int maxn = 200000 + 5;
    vector<pair<int, int> > ve[maxn];
    int tree[maxn << 2], lazy[maxn << 2];
    int n, q;
    int a[maxn], mex[maxn];
    bool vis[maxn];
    int nxt[maxn], pos[maxn];
    
    void build_tree(int l, int r, int o){
        lazy[o] = -1;
        if (l == r){
            tree[o] = mex[l]; return ;
        }
        int mid = (l + r) / 2;
        build_tree(l, mid, o << 1);
        build_tree(mid + 1, r, o << 1 | 1);
        tree[o] = min(tree[o << 1], tree[o << 1 | 1]);
    }
    
    void push_down(int o){
        int lb = o << 1, rb = o << 1 | 1;
        if (lazy[lb] == -1 || lazy[lb] > lazy[o]){
            lazy[lb] = lazy[o];
            tree[lb] = min(tree[lb], lazy[lb]);
        }
        if (lazy[rb] == -1 || lazy[rb] > lazy[o]){
            lazy[rb] = lazy[o];
            tree[rb] = min(tree[rb], lazy[rb]);
        }
        tree[o] = -1;
    }
    
    int query(int x, int l, int r, int o){
        if (x == l && x == r){
            return tree[o];
        }
        if (lazy[o] != -1) push_down(o);
        int mid = (l + r) / 2;
        if (x <= mid) return query(x, l, mid, o << 1);
        if (x > mid) return query(x, mid + 1, r, o << 1 | 1);
    }
    
    void update(int ql, int qr, int l, int r, int o, int val){
        if (ql <= l && qr >= r){
            if (lazy[o] == -1) lazy[o] = val;
            lazy[o] = min(lazy[o], val);
            tree[o] = min(lazy[o], tree[o]);
            return ;
        }
        if (lazy[o] != -1)push_down(o);
        int mid = (l + r) / 2;
        if (ql <= mid) update(ql, qr, l, mid, o << 1, val);
        if (qr > mid) update(ql, qr, mid + 1, r, o << 1 | 1, val);
        tree[o] = min(tree[o << 1], tree[o << 1 | 1]);
    }
    int ans[maxn];
    void solve(){
        build_tree(1, n, 1);
        for (int i = 1; i <= n; i++){
            for (int j = 0; j < ve[i].size(); j++){
                int pos = ve[i][j].fi, id = ve[i][j].se;
                ans[id] = query(pos, 1, n, 1);
            }
            int lb = i + 1, rb = nxt[i] - 1;
            if (lb <= rb) update(lb, rb, 1, n, 1, a[i]);
        }
        for (int i = 1; i <= q; i++){
            printf("%d
    ", ans[i]);
        }
    }
    
    int main(){
        cin >> n >> q;
        for (int i = 1; i <= n; i++) {
            scanf("%d", a + i);
            vis[a[i]] = true;
            mex[i] = mex[i - 1];
            while (vis[mex[i]]) mex[i]++;
            pos[i] = n + 1;
        }
        for (int i = 0; i <= n; i++) pos[i] = n + 1;
        for (int i = n; i >= 1; i--){
            nxt[i] = pos[a[i]];
            pos[a[i]] = i;
        }
        for (int i = 1; i <= q; i++){
            int l, r; scanf("%d%d", &l, &r);
            ve[l].pb(mk(r, i));
        }
        solve();
        return 0;
    }
    View Code
  • 相关阅读:
    Centos 6.5 在 Dell 服务器安装的记录
    【转载】你真的了解补码吗
    【转载】我对补码的理解
    记录一下家里双路由实现wifi漫游功能
    中国大学MOOC | C语言程序设计入门 第8周编程练习 翁恺
    华为卡刷包线刷方法
    串口通信
    端口复用和端口重映射
    软件仿真和硬件仿真
    FPGA之四位LED灯
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6668367.html
Copyright © 2011-2022 走看看