hdu 3627 Giant For //线段树

来源:互联网 发布:逆战混沌宏数据 编辑:程序博客网 时间:2024/05/21 21:48


首先以x为第一关键字,y为第二关键字进行排序,离散化

得到一个长度为num的数组(任何一次查询对应的点都能在这个数组中找到)

对此进行建树

比如进行第i次操作

找到其在数组中对应的点pos

那么pos--->num这里面的所有点的x值都大于等于pos点

看这一段序列是否有值的纵坐标大于pos点(还要注意可能会出现x坐标相同的情况,这个其实可以通过预处理找到某一段x值都大于pos点的,我懒得写了)

线段树维护一个最大的纵坐标的值,这个是降低复杂度的关键


#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define LL(x)  (x<<1)#define RR(x)  ((x<<1)|1)const int MAXN = 200000 + 1234;struct Seg_Tree{    int l, r, vmax;//vamx --> col    int mid()    {        return (l + r) >> 1;    }} tree[MAXN * 4];struct node{    int l, r, op, id;} que[MAXN], tmp[MAXN];int mark[MAXN];int remark[MAXN];bool cmp(node a, node b){    if(a.l == b.l)  return a.r < b.r;//若横坐标相同,则按纵坐标从小到大排序    return a.l < b.l;}void build(int l, int r, int idx){    tree[idx].l = l;    tree[idx].r = r;    tree[idx].vmax = 0;    if(l == r) return ;    int mid = tree[idx].mid();    build(l, mid, LL(idx));    build(mid+1, r, RR(idx));}void update_info(int idx){    tree[idx].vmax = max(tree[LL(idx)].vmax, tree[RR(idx)].vmax);}void insert(int col, int id, int idx){    if(tree[idx].l == tree[idx].r)    {        tree[idx].vmax = col;        return;    }    int mid = tree[idx].mid();    if(id > mid)  insert(col, id, RR(idx));    else if(id <= mid) insert(col, id, LL(idx));    update_info(idx);}void remove(int id, int idx){    if(tree[idx].l == tree[idx].r)    {        tree[idx].vmax = 0;        return;    }    int mid = tree[idx].mid();    if(id > mid)  remove(id, RR(idx));    else if(id <= mid) remove(id, LL(idx));    update_info(idx);}int find(int row, int col, int l, int r, int idx)//在l-->r这个区间找一个值大于row和col的{    if(tree[idx].vmax <= col)  return -1;    if(tree[idx].l == tree[idx].r)    {        if(que[remark[tree[idx].l]].l > row)        {            return remark[tree[idx].l];        }        else return -1;    }    int mid = tree[idx].mid();    //尽量找左边的    if(l <= mid)    {        //int ans = find(row, col, l, mid, LL(idx));这种错误不要再犯了!        int ans = find(row, col, l, r, LL(idx));        if(ans != -1)  return ans;    }    if(r > mid)    {        //int ans = find(row, col, mid+1, r, RR(idx));        int ans = find(row, col, l, r, RR(idx));        if(ans != -1)  return ans;    }    return -1;}int main(){    int n;    char str[10];    int cas = 1;    while(scanf("%d", &n) != EOF)    {        if(n == 0)  break;        if(cas > 1) printf("\n");        for(int i = 1; i <= n; i++)        {            scanf("%s%d%d", str, &que[i].l, &que[i].r);            tmp[i].l = que[i].l;            tmp[i].r = que[i].r;            tmp[i].id = que[i].id = i;            if(strcmp(str, "add") == 0)  tmp[i].op = que[i].op = 1;            else if(strcmp(str, "remove") == 0)  tmp[i].op = que[i].op = 2;            else if(strcmp(str, "find") == 0)  tmp[i].op = que[i].op = 3;        }        //开始离散化        sort(tmp + 1, tmp + 1 + n, cmp);        tmp[0].l = -10000;        tmp[0].r = -10000;        int num = 0;        for(int i = 1; i <= n; i++)        {            if(tmp[i].l == tmp[i-1].l && tmp[i].r == tmp[i-1].r)            {                mark[tmp[i].id] = num;            }            else            {                ++num;                mark[tmp[i].id] = num;                remark[num] = tmp[i].id;            }        }        //离散化完了以后开始建树        build(1, num, 1);        printf("Case %d:\n", cas++);        for(int i = 1; i <= n; i++)        {            if(que[i].op == 1)  insert(que[i].r, mark[que[i].id], 1);            else if(que[i].op == 2)  remove(mark[que[i].id], 1);            else            {                int ans = find(que[i].l, que[i].r, mark[que[i].id], num, 1);                if(ans == -1)  printf("-1\n");                else printf("%d %d\n", que[ans].l, que[ans].r);            }        }    }    return 0;}


原创粉丝点击