[線段樹+離散化+單點查詢] HDOJ – 4325 Flowers

來源:互聯網
上載者:User

一年沒寫線段樹, 全憑回憶加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);}}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.