Codeforces 19D(线段树+离散化)

题意:题意很好理解,三种操作: (1)add x y,添加坐标(x,y),(2)del x y,删除坐标(x,y),(3)find x y,找到并输出严格大于(x,y)的坐标里的最小坐标。

题解:因为点有200000个,而点坐标最大到1e9,所以要离散化处理,我们只需要对x离散化,然后每个x对应一个set存y,然后每次修改操作的时候,根据set内的值维护最大y。

#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
const int N = 200100;
struct Point {
    int x, y;
    Point(int a = -1, int b = -1): x(a), y(b) {}
}P[N];
set<int> py[N];
struct Tree {
    int maxp;
}tree[N << 2];
int n, num[N], res;
char str[N][10];

void build(int k, int left, int right) {
    tree[k].maxp = -1;
    if (left != right) {
        int mid = (left + right) / 2;
        build(k * 2, left, mid);
        build(k * 2 + 1, mid + 1, right);
    }
}

void pushup(int k) {
    tree[k].maxp = max(tree[k * 2].maxp, tree[k * 2 + 1].maxp);
}

void modify(int k, int left, int right, int pos) {
    if (left == right) {
        if (py[pos].size())
            tree[k].maxp = *(--py[pos].end());
        else
            tree[k].maxp = -1;
        return;
    }
    int mid = (left + right) / 2;
    if (pos <= mid)
        modify(k * 2, left, mid, pos);
    else
        modify(k * 2 + 1, mid + 1, right, pos);
    pushup(k);
}

void query(int k, int left, int right, int pos, int p) {
    if (right <= pos)
        return;
    if (tree[k].maxp <= p)
        return;
    if (left == right) {
        res = left;
        return;
    }
    int mid = (left + right) / 2;
    query(k * 2, left, mid, pos, p);
    if (res == -1)
        query(k * 2 + 1, mid + 1, right, pos, p);
}

int main() {
    scanf("%d", &n);
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%s%d%d", str[i], &P[i].x, &P[i].y);
        if (str[i][0] == ‘a‘)
            num[++cnt] = P[i].x;
    }
    sort(num + 1, num + 1 + cnt);
    cnt = unique(num + 1, num + 1 + cnt) - (num + 1);
    for (int i = 1; i <= cnt; i++)
        py[i].clear();
    if (cnt == 0)
        tree[1].maxp = -1;
    else
        build(1, 1, cnt);
    for (int i = 1; i <= n; i++) {
        int pos = upper_bound(num + 1, num + 1 + cnt, P[i].x) - (num + 1);
        if (str[i][0] == ‘a‘) {
            py[pos].insert(P[i].y);
            modify(1, 1, cnt, pos);
        }
        else if (str[i][0] == ‘r‘) {
            py[pos].erase(P[i].y);
            modify(1, 1, cnt, pos);
        }
        else {
            res = -1;
            if (pos <= cnt)
                query(1, 1, cnt, pos, P[i].y);
            if (res == -1)
                printf("-1\n");
            else
                printf("%d %d\n", num[res], *py[res].upper_bound(P[i].y));
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 08:38:26

Codeforces 19D(线段树+离散化)的相关文章

POJ_2528 Mayor&#39;s poster(线段树+离散化)

题目请点我 题解: 这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷.把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变. 举个例子: 区间:[2,6],[4,8],[6,10] 我们进行下面对应: 2 4 6 8 10 1 2 3 4 5 则原区间变为[1,3],[2,4],[3,5].可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

HDU5124:lines(线段树+离散化)或(离散化思想)

http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which is covered by the most lines. John wants to know how many lines cover A. Input The first line conta

hdu1828 Picture(线段树+离散化+扫描线)两种方法

C - Picture Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

hdu 5124 lines (线段树+离散化)

lines Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 620    Accepted Submission(s): 288 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which

poj2528 线段树+离散化

1 //Accepted 1960K 110MS 2 //线段树+离散化 3 //把所有的坐标排序,从小到大编号,建立线段树 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 using namespace std; 11 /** 1

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj2528--Mayor&#39;s posters(线段树+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41785   Accepted: 12164 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post