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;}
- hdu 3627 Giant For //线段树
- (线段树 + 离散化 ) hdu 3627 Giant For
- 【线段树】 HDOJ 3627 Giant For
- hdu 3627 Giant For
- hdu 3627 Giant For
- hdoj 3627 Giant For
- hdu 3627 Giant For(map+set模拟)
- hdu 1754 线段树
- hdu 1754 线段树
- HDU 1698 线段树
- hdu 1754 线段树
- 【线段树】hdu 1754
- hdu-1166 线段树
- HDU-2688 线段树
- HDU 4027 线段树
- HDU-1166 线段树
- hdu 1166 线段树
- hdu 1754 线段树
- C语言结构体中的函数指针与函数
- vc++6.0 和Opencv1.0 实现将捕获的视频转化为图片
- linux中为什么要随机函数栈的起始地址
- JVM加载class文件的原理
- softirq,tasklet,workqueue
- hdu 3627 Giant For //线段树
- set的用法
- 套接字相关数据结构和格式转化
- ASP.NET页面间数据传递的方法
- ZigBee协议介绍
- Altium Designer部分快捷键和使用技巧
- 一年搞死HP通关攻略
- 同步编程的注意点
- 美科学家研制可自行组装微型磁粒机器人