• CC Sereja and Ballons (主席树)


    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

    题意:有n个盒子,每个盒子有若干个气球,每次操作可以拿走某个盒子的一个气球,然后 给出一些区间,问每次操作后有多少个区间的盒子全为空。

    http://www.codechef.com/AUG13/problems/SEABAL

    做法:用链表维护一下当前位置前一个非0位置,下一个非0位置。

    如果当前位置为k,前一个非0位置为l,下一个非0位置为r。

    那么当前位置减为了0,此时增加的区间应该是左端点在(l,k] ,右端点在[k,r)。

    那么接下来就是查询一下有多少个区间满足这个条件。

    用主席树维护以每个位置为区间右端点的左端点位置。

    #include <iostream>
    #include <cstdio>
    #include <set>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #define mem(a,b) memset (a , b , sizeof(a))
    using namespace std;
    const int N = 100005;
    const int M = 30000005;
    struct Node {
        int l , r;
        void input () {
            scanf ("%d %d" , &l , &r);
        }
        bool operator < (const Node &n) const {
            return r < n.r;
        }
    }que[N];
    int n , m , q , a[N]; 
    int T[M] , lson[M] , rson[M] , sum[M] , tot = 0;
    int l[N] , r[N];
    int bulid (int l , int r) {
        int root = ++ tot;
        sum[root] = 0;
        if (l != r) {
            int m = (l + r) >> 1;
            lson[root] = bulid (l , m);
            rson[root] = bulid (m + 1 , r);
        }
        return root;
    }
    int update (int root , int l , int r , int pos) {
        int newroot = ++ tot;
        sum[newroot] = sum[root] + 1;
        if (l != r) {
            int m = (l + r) >> 1;
            if (pos <= m) {
                lson[newroot] = update (lson[root] , l , m , pos);
                rson[newroot] = rson[root];
            }
            else {
                rson[newroot] = update (rson[root] , m + 1 , r , pos);
                lson[newroot] = lson[root];
            }
        }
        //cout << sum[newroot] << " " << sum[lson[newroot]] << " " << sum[rson[newroot]] << endl;;
        return newroot;
    }
    int query (int root , int L , int R , int l , int r) {
        if (L == l && R == r) {
            return sum[root];
        }
        int m = (L + R) >> 1;
        if (r <= m) return query (lson[root] , L , m , l , r);
        else if (l > m) return query (rson[root] , m + 1 , R , l , r);
        else return query (lson[root] , L , m , l , m) + query (rson[root] , m + 1 , R , m + 1 , r);
    }
    void out (int root , int l , int r) {
        cout << l << " " << r << " " << sum[root] << endl;
        if (l != r) {
            int m = (l + r) >> 1;
            out (lson[root] , l , m);
            out (rson[root] , m + 1 , r);
        }
    }
    int main () {
        // freopen ("input.txt" , "r" , stdin);
        // freopen ("output.txt" , "w" , stdout);
        scanf ("%d %d" , &n , &m);
        l[0] = 0; r[n + 1] = n + 1;
        for (int i = 1 ; i <= n ; i ++) {
            scanf ("%d" , &a[i]);
            l[i] = i - 1;
            r[i] = i + 1;
        }
        for (int i = 0 ; i < m ; i ++) {
            que[i].input();
        }
        sort (que , que + m);
        T[0] = bulid (1 , n);
        for (int i = 1 , j = 0 ; i <= n ; i ++) {
            T[i] = T[i - 1];
            while (j < m && que[j].r == i) {
                T[i] = update (T[i] , 1 , n , que[j].l);
                j ++;
            }
            // cout << "root : " << i << endl;
            // out (T[i] , 1 , n);
        }
        scanf ("%d" , &q);
        int ans = 0;
        while (q --) {
            int k;
            scanf ("%d" , &k);
            k += ans;
            //cout << k << endl;
            a[k] --;
            if (a[k] == 0) {
                int L = l[k] , R = r[k];
                int ret = query (T[R - 1] , 1 , n , L + 1 , k) - query (T[k - 1] , 1 , n , L + 1 , k); 
                ans += ret;
                // cout << "ret :" << ret << endl;
                if (r[k] <= n) l[r[k]] = l[k];  
                if (l[k] >= 1) r[l[k]] = r[k];
            }
            printf ("%d
    " , ans);                
        }
        return 0;
    }


  • 相关阅读:
    poj 1013 Counterfeit Dollar
    poj百练2973:Skew数 进制问题
    poj百练2972 进制问题
    poj2080 Calendar
    POJ 1928 The Peanuts
    EXCEL打开CSV文件乱码的解决方法
    希望博客园做个软件职业生存状态调查问卷
    Linq使用Group By [转]
    ADO.NET 从DataTable中获取某列含有的不同值的几种方式
    本该遭拒的十大科技专利:苹果滑动解锁上榜[转]
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3258023.html
Copyright © 2020-2023  润新知