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