• 2018牛客多校第六场 I.Team Rocket


    题意:

      给出n个区间和m个点(点按顺序给出且强制在线)。每个区间只会被第一个他包含的点摧毁。问每个点能摧毁多少个区间以及每个区间是被哪个点摧毁的。

    题解:

      将n个区间按照左端点排序,然后用vector(储存左端点,右端点,id)初始化线段树。

      初始化的方法是:对于线段树的n个叶子节点,即为排好序的n个区间。对于其他节点,将左右儿子按照右端点大小归并(归并是线性复杂度)。

      还要维护每个节点左端点的最小值(用来剪枝)和最大值(用来判断可行性)。

      每个区间只会被第一个他包含的点摧毁,所以用vis数组标记一个区间是否已被摧毁。

      每次遍历vector数组后使用erase会T掉,可以再维护一个信息表示上次遍历到的位置,这次从这个位置开始遍历。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+10;
    const int mod = 998244353;
    int t, n, m;
    int x, y, lst, judge;
    int ans[N], vis[N];
    struct node {
        int l, r, id;
        bool operator < (const node &a) {
            return l == a.l ? r > a.r : l < a.l;
        }
    }a[N];
    int min_L[N<<2], max_L[N<<2], L[N<<2];
    vector<node> g[N<<2];  
    void merge(int id) {
        int lch = id<<1, rch = id<<1|1;
        max_L[id] = max(max_L[lch], max_L[rch]);
        min_L[id] = min(min_L[lch], min_L[rch]);
        int len1 = g[lch].size(), len2 = g[rch].size();
        int l1 = 0, l2 = 0;
        while(l1 < len1 || l2 < len2) {
            if(l1 == len1 || l2 != len2 && g[rch][l2].r > g[lch][l1].r) g[id].push_back(g[rch][l2++]);
            else g[id].push_back(g[lch][l1++]);
        }
    }
    void build(int id, int l, int r) {
        g[id].clear();
        L[id] = 0;
        if(l == r) {
            g[id].push_back(a[l]);
            max_L[id] = min_L[id] = a[l].l;
            return ;
        }
        int mid = l+r >> 1;
        build(id<<1, l, mid);
        build(id<<1|1, mid+1, r);
        merge(id);
    }
    int query(int id, int l, int r, int ql, int num) {
        if(min_L[id] > ql) return 0;
        if(max_L[id] <= ql) {
            int cnt = L[id], tot = 0;
            int len = g[id].size();
            while(cnt < len && g[id][cnt].r >= ql) {
                int v = g[id][cnt].id;
                if(!vis[v]) {
                    lst = 1ll*lst*v%mod;
                    judge++;
                    ans[v] = num;
                    vis[v] = 1;
                    tot++;
                }
                cnt++;
            }
            L[id] = cnt;
            return tot;
        }
        int res = 0;
        int mid = l+r>>1;
        res += query(id<<1, l, mid, ql, num);
        res += query(id<<1|1, mid+1, r, ql, num);
        return res;
    }
    int main() {
        scanf("%d", &t);
        for(int casee = 1; casee <= t; casee++) {
            printf("Case #%d:
    ", casee);
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d%d", &a[i].l, &a[i].r);
                ans[i] = vis[i] = 0;
                a[i].id = i;
            }
            sort(a+1, a+n+1);
            build(1, 1, n);
            lst = 0;
            for(int i = 1; i <= m; i++) {
                scanf("%d", &y);
                x = y^(lst % mod);
                lst = 1, judge = 0;
                printf("%d
    ", query(1, 1, n, x, i));
                if(!judge) lst = 0;
            }
            for(int i = 1; i < n; i++) printf("%d ", ans[i]);
            printf("%d
    ", ans[n]);
        }
    }
    View Code
  • 相关阅读:
    visual studio 2010设置
    Win7 x64 PL/SQL 连接 Oralce 提示 Could not initialize "%ORACLE_HOME%\bin\oci.dll"
    jxl导入/导出excel
    struts2的action与jsp之间传递参数
    web服务器、容器和中间件
    myeclipse trial expired 注册码解决办法(可用于8.5)
    Java中的内部类
    JS的trim()方法
    struts2 <s:property>用法
    EL表达式的使用
  • 原文地址:https://www.cnblogs.com/Pneuis/p/9425413.html
Copyright © 2020-2023  润新知