1. 程式人生 > >wenbao與線段樹

wenbao與線段樹

iostream while fin struct sum names font \n bsp

敵兵布陣

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e5;
 4 struct Node{
 5     int left;
 6     int right;
 7     int sum;
 8 } N[maxn*4];
 9 
10 void init(int l,int r,int num){
11     N[num].left = l;
12     N[num].right = r;
13     N[num].sum = 0;
14
if(N[num].left == N[num].right) return ; 15 int mid = (N[num].left + N[num].right) >> 1; 16 init(l, mid, num<<1); 17 init(mid+1, r, num<<1|1); 18 } 19 20 void add(int x,int y,int num){ 21 if(N[num].left == N[num].right){ 22 N[num].sum += y; 23
return ; 24 } 25 int mid = (N[num].left + N[num].right) >> 1; 26 if(x <= mid) 27 add(x, y, num<<1); 28 else 29 add(x, y, num<<1|1); 30 N[num].sum = N[num<<1].sum + N[num<<1|1].sum; 31 } 32 33 int findn(int ll,int
rr,int num){ 34 if(N[num].left == ll && N[num].right == rr){ 35 return N[num].sum; 36 } 37 int mid = N[num].left + N[num].right>>1; 38 if(ll > mid){ 39 return findn(ll, rr, num<<1|1); 40 } 41 else if(rr <= mid){ 42 return findn(ll, rr, num<<1); 43 } 44 else 45 return findn(ll, mid, num<<1) + findn(mid+1, rr, num<<1|1); 46 } 47 48 int main(){ 49 int t, n, m, countn = 1; 50 char str[20]; 51 scanf("%d", &t); 52 while(t--){ 53 scanf("%d", &n); 54 init(1,n,1); 55 for(int i = 1; i <= n; i++){ 56 scanf("%d", &m); 57 add(i, m, 1); 58 } 59 printf("Case %d:\n", countn++); 60 while(~scanf("%s", str)){ 61 if(str[0] == E) 62 break; 63 if(str[0] == A){ 64 int a, b; 65 scanf("%d%d", &a, &b); 66 add(a, b, 1); 67 } 68 if(str[0] == S){ 69 int a, b; 70 scanf("%d%d", &a, &b); 71 add(a, -b, 1); 72 } 73 if(str[0] == Q){ 74 int a, b; 75 scanf("%d%d", &a, &b); 76 printf("%d\n", findn(a,b,1)); 77 } 78 } 79 } 80 return 0; 81 }

-------------------------------------------------------------------

http://poj.org/problem?id=2828

排隊。。此題妙哉

目的是求第k大數,線段樹和都可以樹狀數組

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cmath>
 4 using namespace std;
 5 #define ls node<<1
 6 #define rs node<<1|1
 7 const int maxn = 200009;
 8 int n, a[maxn], b[maxn], c[maxn];
 9 struct Node{
10     int l, r, num;
11 }sum[maxn*4];
12 void build(int l, int r, int node){
13     sum[node].l = l, sum[node].r = r, sum[node].num = r-l+1;
14     if(l == r) return;
15     int mid = (l+r)>>1;
16     build(l, mid, ls);
17     build(mid+1, r, rs);
18 }
19 int add(int id, int node){
20     sum[node].num --;
21     if(sum[node].l == sum[node].r){
22         return sum[node].l;
23     }
24     if(sum[ls].num >= id) add(id, ls);
25     else id -= sum[ls].num, add(id, rs);
26 }
27 int main(){
28     while(~scanf("%d", &n)){
29         build(1, n, 1);
30         for(int i = 0; i < n; ++i){
31             scanf("%d%d", &a[i], &b[i]);
32         }
33         for(int i = n-1; i >= 0; --i){
34             c[add(a[i]+1, 1)] = b[i];
35         }
36         for(int i = 1; i <= n; ++i){
37             printf("%d%c", c[i], i == n ? \n :  );
38         }
39     }
40     return 0;
41 }

-------------------------------------------------------------------

http://poj.org/problem?id=3277

計算陰影面積(離散化+線段樹)

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdio.h>
 4 using namespace std;
 5 #define ll long long
 6 const int maxn = 204000;
 7 ll l[maxn], r[maxn], h[maxn], a[maxn*2], sum[maxn*2], cnt = 0;
 8 int n, num = 0, id = 1;
 9 bool lz[maxn*2];
10 void p(int node){
11     if(lz[node]){
12         sum[node<<1] = max(sum[node<<1], sum[node]);
13         sum[node<<1|1] = max(sum[node<<1|1], sum[node]);
14         lz[node<<1] = lz[node<<1|1] = true;
15         lz[node] = false;
16     }
17 }
18 void add(int lx, int rx, ll val, int lxx, int rxx, int node){
19     if(lx <= lxx && rxx <= rx){
20         sum[node] = max(sum[node], val);
21         lz[node] = true;
22         return ;
23     }
24     p(node);
25     int mid = (lxx+rxx) >> 1;
26     if(lx <= mid) add(lx, rx, val, lxx, mid, node<<1);
27     if(mid < rx) add(lx, rx, val, mid+1, rxx, node<<1|1);
28 }
29 void q(int lx, int rx, int node){
30     p(node);
31     if(rx == lx){
32         cnt += (a[id]-a[id-1])*sum[node];
33         id ++;
34         return;
35     }
36     int mid = (lx+rx) >> 1;
37     q(lx, mid, node<<1);
38     q(mid+1, rx, node<<1|1);
39 }
40 int main(){
41     scanf("%d", &n);
42     for(int i = 0; i < n; ++i){
43         scanf("%lld%lld%lld", &l[i], &r[i], &h[i]);
44         a[num++] = l[i], a[num++] = r[i];
45     }
46     sort(a, a+num);
47     num = unique(a, a+num) - a;
48     for(int i = 0; i < n; ++i){
49         int xx = lower_bound(a, a+num, l[i]) - a;
50         int yy = lower_bound(a, a+num, r[i]) - a;
51         add(xx+1, yy, h[i], 1, num, 1);
52     }
53     q(1, num, 1);
54     printf("%lld\n", cnt);
55     return 0;
56 }

-------------------------------------------------------------------

http://poj.org/problem?id=2528

幾張海報(離散化+線段樹)

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 10009;
 7 struct Node{
 8     int l, r;
 9 }T[maxn];
10 int a[maxn*6], sum[maxn*16], cnt;
11 bool vis[maxn*6];
12 void pd(int node){
13     if(sum[node] != -1){
14         sum[node<<1] = sum[node<<1|1] = sum[node];
15         sum[node] = -1;
16     }
17 }
18 void add(int l, int r, int val, int ll, int rr, int node){
19     if(l <= ll && rr <= r){
20         sum[node] = val;
21         return;
22     }
23     pd(node);
24     int mid = (ll+rr) >> 1;
25     if(l <= mid) add(l, r, val, ll, mid, node<<1);
26     if(mid < r) add(l, r, val, mid+1, rr, node<<1|1);
27 }
28 void find(int ll, int rr, int node){
29     if(sum[node] != -1){
30         if(!vis[sum[node]]) cnt ++, vis[sum[node]] = true;
31         return;
32     }
33     if(ll == rr) return;
34     int mid = (ll+rr) >> 1;
35     find(ll, mid, node<<1);
36     find(mid+1, rr, node<<1|1);
37 }
38 int main(){
39     int t, n;
40     scanf("%d", &t);
41     while(t--){
42         int num = 0;
43         scanf("%d", &n);
44         for(int i = 0; i < n; ++i){
45             scanf("%d%d", &T[i].l, &T[i].r);
46             a[num++] = T[i].l, a[num++] = T[i].r;
47         }
48         sort(a, a+num);
49         int m = unique(a, a+num) - a;
50         int xx = m;
51         for(int i = 1; i < m; ++i){
52             if(a[i]-a[i-1] > 1) a[xx++] = a[i-1]++;
53         }
54         sort(a, a+xx);
55         memset(sum, -1, sizeof(sum));
56         for(int i = 0; i < n; ++i){
57             int l = lower_bound(a, a+xx, T[i].l) - a;
58             int r = lower_bound(a, a+xx, T[i].r) - a;
59             add(l, r, i, 0, xx, 1);
60         }
61         memset(vis, false, sizeof(vis)), cnt = 0;
62         find(0, xx, 1);
63         printf("%d\n", cnt);
64     }
65     return 0;
66 }

-------------------------------------------------------------------

-------------------------------------------------------------------

-------------------------------------------------------------------

只有不斷學習才能進步!

wenbao與線段樹