[线段树+离散化+单点查询] HDOJ - 4325 Flowers
来源:互联网 发布:做淘宝怎么做需要哪些 编辑:程序博客网 时间:2024/06/05 01:12
一年没写线段树, 全凭回忆加YY能1A好哈皮..............
很裸的线段树, 就是需要先离散化.
离散化我记得有lower_bound这种东西, 但是想不起来怎么用了...所以这里是YY了用了个map然后O(n)循环进行离散值对应...
预备:
1/ STL - unique, 接受两个指针(第三个参数为可选自定义相等比较器, 相等返回true), 实现呢就是从头到尾扫一遍, 利用相等元素相邻(若不满足则要先sort). 将区间重复的元素都放到末尾, 返回前面不重复区间的最后一个元素地址.
template <class ForwardIterator> ForwardIterator unique ( ForwardIterator first, ForwardIterator last ){ ForwardIterator result=first; while (++first != last) { if (!(*result == *first)) // or: if (!pred(*result,*first)) for the pred version *(++result)=*first; } return ++result;}2/ STL - lower_bound, 接受两个指针跟要找的值(第四个可选参数为自定义小于比较器, 小于返回true),用于在有序的区间中查找首个不小于(小于等于)某值的元素(大于等于某值), 返回下确界元素的地址. 目测用的二分.
template <class ForwardIterator, class T> ForwardIterator lower_bound ( ForwardIterator first, ForwardIterator last, const T& value ){ ForwardIterator it; iterator_traits<ForwardIterator>::distance_type count, step; count = distance(first,last); while (count>0) { it = first; step=count/2; advance (it,step); if (*it<value) // or: if (comp(*it,value)), for the comp version { first=++it; count-=step+1; } else count=step; } return first;}
下面给出利用unique / lower_bound 来进行离散化的部分代码:
sort(all, all+idx);int tot = unique(all, all+idx) - all;build(1, tot, 1);...int x = lower_bound(all, all+tot, st[i]) - all;int y = lower_bound(all, all+tot, en[i]) - all;简言之就是, 用unique来剔除重复元素, 用lower_bound来查找元素位置(unique后的区间已经是不重复的了, 所以只是查找而已, 所以你甚至可以用upper_bound, 只不过upper_bound返回的是大于value()不包含等于, 所以要用 upper_bound(...)-1, 等价于 lower_bound(...) ).
代码(原先):
#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<string>#include<vector>#include<map>#include<algorithm>using namespace std;int Rint() { int x; scanf("%d", &x); return x; }#define FOR(i, a, b) for(int i=(a); i<=(b); i++)#define FORD(i,a,b) for(int i=(a);i>=(b);i--)#define REP(x) for(int i=0; i<(x); i++)typedef long long int64;#define INF (1<<30)#define bug(s) cout<<#s<<"="<<s<<" "#define MAXN 100002struct node{int l, r, v;int add;//lazy-add}a[MAXN*2*4];//1-th//10^9离散化, 10^5条线段, 最多可能产生 2*10^5个点void pushdown(int e){if(a[e].add){if(a[e].l != a[e].r)//若不是叶子, 则下推{a[e<<1].add += a[e].add;a[e<<1|1].add += a[e].add;//pushdown(e<<1);//不能递归下推, 不然也不是lazy了//pushdown(e<<1|1);}a[e].v += a[e].add;a[e].add = 0;}}void build(int l, int r, int e){a[e].l = l;a[e].r = r;a[e].v = a[e].add = 0;if(l == r){return;}else{int mid = (l+r)>>1;build(l, mid, e<<1);build(mid+1, r, e<<1|1);}}void add(int l, int r, int e){//if(l!=r)//不用到叶子节点, 不然延迟处理就没意义了, 效率退化必TLE~- -if(l<=a[e].l && a[e].r<=r){a[e].add += 1;}else{int mid = (a[e].l+a[e].r)>>1;if(l<=mid)add(l, r, e<<1);if(mid+1<=r)//注意是 mid+1add(l, r, e<<1|1);}}int query(int e, int p){pushdown(e);if(a[e].l == p && a[e].r == p){return a[e].v;}else{//pushdown(e);//在这里推不够下...wa1int mid = (a[e].l+a[e].r)>>1;if(p<=mid)//mid算 左边?return query(e<<1, p);elsereturn query(e<<1|1, p);}}int n, m;//m = query timesint st[MAXN], en[MAXN];int q[MAXN];int all[MAXN*3];int idx;map<int, int> tolow;//e.g. tolow[234] = 1;int main(){int t = Rint();FOR(T, 1, t){tolow.clear();idx = 0;printf("Case #%d:\n", T);n = Rint();m = Rint();REP(n){st[i] = Rint();en[i] = Rint();all[idx++] = st[i];all[idx++] = en[i];}REP(m){q[i] = Rint();all[idx++] = q[i];}sort(all, all+idx);int rank = 1;REP(idx){int v = all[i];if(tolow[v]) continue;tolow[v] = rank++;//离散后的值从1开始}int tot = tolow.size();build(1, tot, 1);REP(n){add(tolow[st[i]], tolow[en[i]], 1);}REP(m){int ans = query(1, tolow[q[i]]);printf("%d\n", ans);}}}
代码(lower_bound):
#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<string>#include<vector>#include<map>#include<algorithm>using namespace std;int Rint() { int x; scanf("%d", &x); return x; }#define FOR(i, a, b) for(int i=(a); i<=(b); i++)#define FORD(i,a,b) for(int i=(a);i>=(b);i--)#define REP(x) for(int i=0; i<(x); i++)typedef long long int64;#define INF (1<<30)#define bug(s) cout<<#s<<"="<<s<<" "#define MAXN 100002struct node{int l, r, v;int add;//lazy-add}a[MAXN*2*4];//1-th//10^9离散化, 10^5条线段, 最多可能产生 2*10^5个点void pushdown(int e){if(a[e].add){if(a[e].l != a[e].r)//若不是叶子, 则下推{a[e<<1].add += a[e].add;a[e<<1|1].add += a[e].add;//pushdown(e<<1);//不能递归下推, 不然也不是lazy了//pushdown(e<<1|1);}a[e].v += a[e].add;a[e].add = 0;}}void build(int l, int r, int e){a[e].l = l;a[e].r = r;a[e].v = a[e].add = 0;if(l == r){return;}else{int mid = (l+r)>>1;build(l, mid, e<<1);build(mid+1, r, e<<1|1);}}void add(int l, int r, int e){//if(l!=r)//不用到叶子节点, 不然延迟处理就没意义了, 效率退化必TLE~- -if(l<=a[e].l && a[e].r<=r){a[e].add += 1;}else{int mid = (a[e].l+a[e].r)>>1;if(l<=mid)add(l, r, e<<1);if(mid+1<=r)//注意是 mid+1add(l, r, e<<1|1);}}int query(int e, int p){pushdown(e);if(a[e].l == p && a[e].r == p){return a[e].v;}else{//pushdown(e);//在这里推不够下...wa1int mid = (a[e].l+a[e].r)>>1;if(p<=mid)//mid算 左边?return query(e<<1, p);elsereturn query(e<<1|1, p);}}int n, m;//m = query timesint st[MAXN], en[MAXN];int q[MAXN];int all[MAXN*3];int idx;map<int, int> tolow;//e.g. tolow[234] = 1;int main(){int t = Rint();FOR(T, 1, t){tolow.clear();idx = 0;printf("Case #%d:\n", T);n = Rint();m = Rint();REP(n){st[i] = Rint();en[i] = Rint();all[idx++] = st[i];all[idx++] = en[i];}REP(m){q[i] = Rint();all[idx++] = q[i];}sort(all, all+idx);int tot = unique(all, all+idx) - all;build(1, tot, 1);REP(n){int x = lower_bound(all, all+tot, st[i]) - all + 1;int y = lower_bound(all, all+tot, en[i]) - all + 1;add(x, y, 1);}REP(m){int x = lower_bound(all, all+tot, q[i]) - all + 1;int ans = query(1, x);printf("%d\n", ans);}}}
代码(upper_bound):
#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<string>#include<vector>#include<map>#include<algorithm>using namespace std;int Rint() { int x; scanf("%d", &x); return x; }#define FOR(i, a, b) for(int i=(a); i<=(b); i++)#define FORD(i,a,b) for(int i=(a);i>=(b);i--)#define REP(x) for(int i=0; i<(x); i++)typedef long long int64;#define INF (1<<30)#define bug(s) cout<<#s<<"="<<s<<" "#define MAXN 100002struct node{int l, r, v;int add;//lazy-add}a[MAXN*2*4];//1-th//10^9离散化, 10^5条线段, 最多可能产生 2*10^5个点void pushdown(int e){if(a[e].add){if(a[e].l != a[e].r)//若不是叶子, 则下推{a[e<<1].add += a[e].add;a[e<<1|1].add += a[e].add;//pushdown(e<<1);//不能递归下推, 不然也不是lazy了//pushdown(e<<1|1);}a[e].v += a[e].add;a[e].add = 0;}}void build(int l, int r, int e){a[e].l = l;a[e].r = r;a[e].v = a[e].add = 0;if(l == r){return;}else{int mid = (l+r)>>1;build(l, mid, e<<1);build(mid+1, r, e<<1|1);}}void add(int l, int r, int e){//if(l!=r)//不用到叶子节点, 不然延迟处理就没意义了, 效率退化必TLE~- -if(l<=a[e].l && a[e].r<=r){a[e].add += 1;}else{int mid = (a[e].l+a[e].r)>>1;if(l<=mid)add(l, r, e<<1);if(mid+1<=r)//注意是 mid+1add(l, r, e<<1|1);}}int query(int e, int p){pushdown(e);if(a[e].l == p && a[e].r == p){return a[e].v;}else{//pushdown(e);//在这里推不够下...wa1int mid = (a[e].l+a[e].r)>>1;if(p<=mid)//mid算 左边?return query(e<<1, p);elsereturn query(e<<1|1, p);}}int n, m;//m = query timesint st[MAXN], en[MAXN];int q[MAXN];int all[MAXN*3];int idx;map<int, int> tolow;//e.g. tolow[234] = 1;int main(){int t = Rint();FOR(T, 1, t){tolow.clear();idx = 0;printf("Case #%d:\n", T);n = Rint();m = Rint();REP(n){st[i] = Rint();en[i] = Rint();all[idx++] = st[i];all[idx++] = en[i];}REP(m){q[i] = Rint();all[idx++] = q[i];}sort(all, all+idx);int tot = unique(all, all+idx) - all;build(1, tot, 1);REP(n){int x = upper_bound(all, all+tot, st[i]) - all;//upper_bound: 查找首个大于value(或comp比较为真)的上确界元素int y = upper_bound(all, all+tot, en[i]) - all;add(x, y, 1);}REP(m){int x = upper_bound(all, all+tot, q[i]) - all;int ans = query(1, x);printf("%d\n", ans);}}}
- [线段树+离散化+单点查询] HDOJ - 4325 Flowers
- hdoj 4325 Flowers 【线段树 + 离散化】【区间更新 单点查询】
- HDOJ 4325 Flowers 【线段树 离散化 区间更新 单点查询】
- HDOJ 题目4325 Flowers(线段树+离散化)
- hdu 4325 Flowers(线段树+离散化)
- hdu 4325 Flowers(离散化+线段树)
- HDU 4325 Flowers (线段树+离散化)
- HDU 4325&& nyoj 600 Flowers【线段树+坐标离散化】
- HDU 4325 Flowers(线段树+离散化)
- hdu_4325 Flowers(离散化+线段树)
- hdu 4325 Flowers 线段树+离散化(要学会离散化的方法)
- hdoj Flowers 4325 (线段树)
- hdoj--4325--Flowers(线段树+二分)
- hdoj 4325 Flowers 【线段树||二分】
- HDOJ 4399 —— 线段树单点更新&单点查询
- hdu 4325 Flowers 离散化+线段树 多校联合赛(三) 第六题
- HDOJ 5124 lines 【线段树 & 离散化】
- hdoj 5124 lines 【离散化 + 线段树】
- POJ图论题目列表
- Sql 语句把重复的记录放到指定列中,用","号分隔
- RESTClient
- polya小结 更新中....
- Oracle的一些常用操作
- [线段树+离散化+单点查询] HDOJ - 4325 Flowers
- jcrop 用法小结
- MFC中用AngleArc函数画图中直线问题
- hdu 1256 画8 (模拟)
- GCC生成的汇编代码
- shell 编程要点
- ADO.NET摘要1
- lua
- undo系列学习之深入浅出事务槽