hdu1698
http://www.notonlysuccess.com/index.php/segment-tree-complete/
hdu1698
#include <iostream> #include <stdio.h>using namespace std;const int maxn = 111111; int a[maxn]; int tree[maxn<<2];//線段樹(shù)的每一個(gè)葉子節(jié)點(diǎn)就是a中的元素,還有其他的非葉子節(jié)點(diǎn),應(yīng)該需要2*maxn+1個(gè)元素 int col[maxn<<2];//如果當(dāng)前節(jié)點(diǎn)有標(biāo)記,就要先更新當(dāng)前節(jié)點(diǎn),并把標(biāo)記傳給孩子void pushUp(int ind) {tree[ind] = tree[2*ind] + tree[2*ind+1]; }void pushDown(int ind, int m) {if(col[ind]) {col[2*ind] = col[2*ind + 1] = col[ind];tree[2*ind] = col[ind] * (m - m/2);tree[2*ind + 1] = col[ind] * m/2;col[ind] = 0;} }void buildTree(int left, int right, int ind) {//找到葉子節(jié)點(diǎn)相應(yīng)的位置, ind是這個(gè)節(jié)點(diǎn)的編號(hào)//left 和 right是這個(gè)節(jié)點(diǎn)所對(duì)應(yīng)的范圍if (left == right) {tree[ind] = 1;col[ind] = 0;return;}int mid = (left + right)/2;buildTree(left, mid, 2*ind);buildTree(mid+1, right, 2*ind + 1);pushUp(ind);}void update(int beg,int end ,int value, int left, int right, int ind) {if(beg <=left && end >= right) {//因?yàn)閜ushDown會(huì)更新孩子節(jié)點(diǎn),所以到達(dá)這個(gè)節(jié)點(diǎn)后,已經(jīng)是最新的值了,不需要再更新了col[ind] = value;tree[ind] = value*(right - left + 1);return;}pushDown(ind, right - left + 1);//把標(biāo)記傳給孩子節(jié)點(diǎn),并更新孩子節(jié)點(diǎn)的值int mid = (left + right) / 2;if (mid >=beg)update(beg,end, value, left, mid, 2*ind);if (mid < end)update(beg,end,value, mid + 1, right, 2*ind+1);pushUp(ind); }int main() {int t,n, m;scanf("%d", &t);for (int i = 0; i < t ; ++i){scanf("%d%d", &n, &m);buildTree(1,n, 1);while(m--) {int a, b, c;scanf("%d%d%d", &a, &b, &c);update(a,b,c,1,n,1);}printf("Case %d: The total value of the hook is %d.\n",t+1 , tree[1]);} }poj2528
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1const int maxn = 11111; bool hash[maxn]; int li[maxn] , ri[maxn]; int X[maxn*3]; int col[maxn<<4]; int cnt;void PushDown(int rt) {if (col[rt] != -1) {col[rt<<1] = col[rt<<1|1] = col[rt];col[rt] = -1;} } void update(int L,int R,int c,int l,int r,int rt) {if (L <= l && r <= R) {col[rt] = c;return ;}PushDown(rt);//對(duì)當(dāng)前節(jié)點(diǎn)要往下傳遞int m = (l + r) >> 1;if (L <= m) update(L , R , c , lson);if (m < R) update(L , R , c , rson); } void query(int l,int r,int rt) {if (col[rt] != -1) {if (!hash[col[rt]]) cnt ++;hash[ col[rt] ] = true;return ;}if (l == r) return ;int m = (l + r) >> 1;query(lson);query(rson); } int Bin(int key,int n,int X[]) {int l = 0 , r = n - 1;while (l <= r) {int m = (l + r) >> 1;if (X[m] == key) return m;if (X[m] < key) l = m + 1;else r = m - 1;}return -1; } int main() {//求得有多少海報(bào)露在外面,不一定要完全露int T , n;scanf("%d",&T);while (T --) {scanf("%d",&n);int nn = 0;for (int i = 0 ; i < n ; i ++) {scanf("%d%d",&li[i] , &ri[i]);X[nn++] = li[i];X[nn++] = ri[i];}sort(X , X + nn);int m = 1;for (int i = 1 ; i < nn; i ++) {//去除重復(fù)的if (X[i] != X[i-1]) X[m ++] = X[i];}for (int i = m - 1 ; i > 0 ; i --) {//添加中間的值if (X[i] != X[i-1] + 1) X[m ++] = X[i-1] + 1;}sort(X , X + m);memset(col , -1 , sizeof(col));for (int i = 0 ; i < n ; i ++) {int l = Bin(li[i] , m , X);//二分查找,用次序替代大數(shù)int r = Bin(ri[i] , m , X);update(l , r , i , 0 , m , 1);}cnt = 0;memset(hash , false , sizeof(hash));query(0 , m , 1);printf("%d\n",cnt);}return 0; }2)在所有不大于30000的自然數(shù)范圍內(nèi)討論一個(gè)問(wèn)題:已知n條線段,把端點(diǎn)依次輸入給你,然后有m(≤30000)個(gè)詢問(wèn),每個(gè)詢問(wèn)輸入一個(gè)點(diǎn),要求這個(gè)點(diǎn)在多少條線段上出現(xiàn)過(guò)。
[問(wèn)題分析]
在這個(gè)問(wèn)題中,我們可以直接對(duì)問(wèn)題處理的區(qū)間建立線段樹(shù),在線段樹(shù)上維護(hù)區(qū)間被覆蓋的次數(shù)。將n條線段插入線段樹(shù),然后對(duì)于詢問(wèn)的每個(gè)點(diǎn),直接查詢被覆蓋的次數(shù)即可。
但是我們?cè)谶@里用這道題目,更希望能夠說(shuō)明一個(gè)問(wèn)題,那就是這道題目完全可以不用線段樹(shù)。我們將每個(gè)線段拆成(L,+1),(R+1,-1)的兩個(gè)事件點(diǎn),每個(gè)詢問(wèn)點(diǎn)也在對(duì)應(yīng)坐標(biāo)處加上一個(gè)詢問(wèn)的事件點(diǎn),排序之后掃描就可以完成題目的詢問(wèn)。我們這里討論的問(wèn)題是一個(gè)離線的問(wèn)題,因此我們也設(shè)計(jì)出了一個(gè)很簡(jiǎn)單的離線算法。線段樹(shù)在處理在線問(wèn)題的時(shí)候會(huì)更加有效,因?yàn)樗S護(hù)了一個(gè)實(shí)時(shí)的信息。
http://dongxicheng.org/structure/segment-tree/
總結(jié)
- 上一篇: 几何分布和超几何分布
- 下一篇: USACO 3.2 Stringsobi