#2:在颓宅的边缘开始试探——4

洛谷3372,才开始学segment tree,初级板子。

 1 #include <cstdio>
 2 #define ll long long
 3 #define maxn 100001
 4 
 5 int n, m;
 6 ll a[maxn], sum[maxn << 2], tag[maxn << 2];
 7 
 8 int ls(int p) {
 9     return p << 1;
10 }
11 
12 int rs(int p) {
13     return p << 1 | 1;
14 }
15 
16 void f(int l, int r, ll k, int p) {
17     tag[p] += k;
18     sum[p] += k*(r-l+1);
19 }
20 
21 void push_down(int l, int r, int p) {
22     int mid = (l + r) >> 1;
23     f(l, mid, tag[p], ls(p));
24     f(mid+1, r, tag[p], rs(p));
25     tag[p] = 0;
26 }
27 
28 void push_up(int p) {
29     sum[p] = sum[ls(p)] + sum[rs(p)];
30 }
31 
32 void build(int l, int r, int p) {
33     tag[p] = 0;
34     if (l == r) {
35         sum[p] = a[l];
36         return;
37     }
38     int mid = (l + r) >> 1;
39     build(l, mid, ls(p));
40     build(mid+1, r, rs(p));
41     push_up(p);
42 }
43 
44 void update(int nl, int nr, ll k, int l, int r, int p) {
45     if (nl <= l && r <= nr) {
46         sum[p] += k*(r-l+1);
47         tag[p] += k;
48         return;
49     }
50     push_down(l, r, p);
51     int mid = (l + r) >> 1;
52     if (nl <= mid)    update(nl, nr, k, l, mid, ls(p));
53     if (mid < nr)    update(nl, nr, k, mid+1, r, rs(p));
54     push_up(p);
55 }
56 
57 ll query(int nl, int nr, int l, int r, int p) {
58     if (nl <= l && r <= nr)    return sum[p];
59     push_down(l, r, p);
60     ll ret = 0ll;
61     int mid = (l + r) >> 1;
62     if (nl <= mid)    ret += query(nl, nr, l, mid, ls(p));
63     if (mid < nr)    ret += query(nl, nr, mid+1, r, rs(p));
64     return ret;
65 }
66 
67 int main() {
68     scanf("%d%d", &n, &m);
69     for (int i = 1; i <= n; i++) {
70         scanf("%lld", &a[i]);
71     }
72     build(1, n, 1);
73     for (int i = 1; i <= m; i++) {
74         int does, x, y;
75         scanf("%d%d%d", &does, &x, &y);
76         if (does == 1) {
77             ll k;
78             scanf("%lld", &k);
79             update(x, y, k, 1, n, 1);
80         } else {
81             printf("%lld\n", query(x, y, 1, n, 1));
82         }
83     }
84     return 0;
85 }
View Code

 

spojGSS3,要维护区间最大连续子段和,得同时用线段树维护前缀、后缀、和、最大连续和。按照上一个板子写到query时发现要query一大堆……只好改用结构体式的板子。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 #define maxn 50001
 6 #define init(a, b) memset(a, b, sizeof(a))
 7 #define inf 0xcfcfcfcf
 8 
 9 int n, m, a[maxn];
10 struct T {
11     int l, r;
12     int sum, lmax, rmax, maxx;
13 }t[maxn<<2];
14 
15 int ls(int p) {
16     return p << 1;
17 }
18 
19 int rs(int p) {
20     return p << 1 | 1;
21 }
22 
23 void push_up(int p) {
24     t[p].sum = t[ls(p)].sum + t[rs(p)].sum;
25     t[p].lmax = max(t[ls(p)].lmax, t[ls(p)].sum + t[rs(p)].lmax);
26     t[p].rmax = max(t[rs(p)].rmax, t[rs(p)].sum + t[ls(p)].rmax);
27     t[p].maxx = max(max(t[ls(p)].maxx, t[rs(p)].maxx), t[rs(p)].lmax+t[ls(p)].rmax);
28 }
29 
30 void build(int l, int r, int p) {
31     t[p].l = l, t[p].r = r;
32     if (l == r) {
33         t[p].sum = t[p].lmax = t[p].rmax = t[p].maxx = a[l];
34         return;
35     }
36     int mid = (l+r) >> 1;
37     build(l, mid, ls(p));
38     build(mid+1, r, rs(p));
39     push_up(p);
40 }
41 
42 void update(int p, int x, int y) {
43     if (t[p].l == t[p].r) {
44         t[p].sum = t[p].lmax = t[p].rmax = t[p].maxx = y;
45         return;
46     }
47     int mid = (t[p].l+t[p].r) >> 1;
48     if (x <= mid)    update(ls(p), x, y);
49     else    update(rs(p), x, y);
50     push_up(p);
51 }
52 
53 T query(int nl, int nr, int p) {
54     if (nl <= t[p].l && t[p].r <= nr)    return t[p];
55     T a, b, ans;
56     a.sum = b.sum = a.lmax = b.lmax = a.rmax = b.rmax = a.maxx = b.maxx = inf;
57     ans.sum = 0;
58     int mid = (t[p].l + t[p].r) >> 1;
59     if (nl <= mid) {
60         a = query(nl, nr, ls(p));
61         ans.sum += a.sum;
62     }
63     if (mid < nr) {
64         b = query(nl, nr, rs(p));
65         ans.sum += b.sum;
66     }
67     ans.maxx = max(max(a.maxx, b.maxx), a.rmax+b.lmax);
68     ans.lmax = max(a.lmax, a.sum+b.lmax);
69     ans.rmax = max(b.rmax, b.sum+a.rmax);
70     if (nl > mid)    ans.lmax = max(ans.lmax, b.lmax);
71     if (nr <= mid)    ans.rmax = max(ans.rmax, a.rmax);
72     return ans;
73 }
74 
75 int main() {
76     scanf("%d", &n);
77 
78     for (int i = 1; i <= n; i++)
79         scanf("%d", &a[i]);
80     build(1, n, 1);
81 
82     scanf("%d", &m);
83     for (int i = 0; i < m; i++) {
84         int q, x, y;
85         scanf("%d%d%d", &q, &x, &y);
86 
87         if (q) {
88             if (x > y)    swap(x, y);
89             printf("%d\n", query(x, y, 1).maxx);
90         } else {
91             update(1, x, y);
92         }
93     }
94 
95     return 0;
96 }
View Code

 

UVALive3938,跟上一题基本是同一道题,要改一改。刘汝佳说的对呀,维护sum为啥要用线段树呀233……不过刘汝佳真的query了一大堆……综合刘汝佳和李煜东的优点自己瞎改一下然后莽了一发,还好A了,不然还得痛苦调bug。

  1 #include <cstdio>
  2 #include <climits>
  3 #include <algorithm>
  4 #define ll long long
  5 #define maxn 500001
  6 #define inf LLONG_MAX
  7 #define P pair<int, int>
  8 #define mp make_pair
  9 using namespace std;
 10 
 11 struct Seg {
 12     int l, r;
 13     int max_prefix, max_suffix;
 14     P max_sub; 
 15 }t[maxn<<2];
 16 
 17 int n, m, kase;
 18 ll prefix_sum[maxn];
 19 
 20 ll sum(int l, int r) {
 21     return prefix_sum[r] - prefix_sum[l-1];
 22 }
 23 
 24 ll sum(P y) {
 25     return sum(y.first, y.second);
 26 }
 27 
 28 P better(P a, P b) {
 29     if (sum(a) != sum(b))    return sum(a) > sum(b) ? a : b;
 30     return a < b ? a : b;
 31 }
 32 
 33 void build(int l, int r, int p) {
 34     t[p].l = l, t[p].r = r;
 35     if (l == r) {
 36         t[p].max_prefix = t[p].max_suffix = l;
 37         t[p].max_sub = mp(l, l);
 38         return;
 39     }
 40 
 41     int mid = (l+r) >> 1;
 42     int ls = p << 1, rs = p << 1 | 1;
 43     build(l, mid, ls);
 44     build(mid+1, r, rs);
 45 
 46     ll v1 = sum(l, t[ls].max_prefix);
 47     ll v2 = sum(l, t[rs].max_prefix);
 48     if (v1 == v2)    t[p].max_prefix = t[ls].max_prefix;
 49     else    t[p].max_prefix = v1 > v2 ? t[ls].max_prefix : t[rs].max_prefix;
 50 
 51     v1 = sum(t[ls].max_suffix, r);
 52     v2 = sum(t[rs].max_suffix, r);
 53     if (v1 == v2)    t[p].max_suffix = t[ls].max_suffix;
 54     else    t[p].max_suffix = v1 > v2 ? t[ls].max_suffix : t[rs].max_suffix;
 55 
 56     t[p].max_sub = better(t[ls].max_sub, t[rs].max_sub);
 57     t[p].max_sub = better(t[p].max_sub, mp(t[ls].max_suffix, t[rs].max_prefix));
 58 }
 59 
 60 Seg query(int l, int r, int p) {
 61     if (l <= t[p].l && t[p].r <= r)    return t[p];
 62 
 63     int mid = (t[p].l + t[p].r) >> 1;
 64     int ls = p << 1, rs = p << 1 | 1;
 65 
 66     if (l > mid)    return query(l, r, rs);
 67     if (r <= mid)    return query(l, r, ls);
 68 
 69     Seg a, b, ans;
 70     a = query(l, r, ls);
 71     b = query(l, r, rs);
 72 
 73     ll v1 = sum(l, a.max_prefix), v2 = sum(l, b.max_prefix);
 74     if (v1 == v2)    ans.max_prefix = a.max_prefix;
 75     else    ans.max_prefix = v1 > v2 ? a.max_prefix : b.max_prefix;
 76 
 77     v1 = sum(a.max_suffix, r), v2 = sum(b.max_suffix, r);
 78     if (v1 == v2)    ans.max_suffix = a.max_suffix;
 79     else    ans.max_suffix = v1 > v2 ? a.max_suffix : b.max_suffix;
 80 
 81     ans.max_sub = better(a.max_sub, b.max_sub);
 82     ans.max_sub = better(ans.max_sub, mp(a.max_suffix, b.max_prefix));
 83     return ans;
 84 }
 85 
 86 int main() {
 87     while (~scanf("%d%d", &n, &m)) {
 88         for (int i = 1; i <= n; i++) {
 89             scanf("%lld", &prefix_sum[i]);
 90             prefix_sum[i] += prefix_sum[i-1];
 91         }
 92         build(1, n, 1);
 93         printf("Case %d:\n", ++kase);
 94         while (m--) {
 95             int l, r;
 96             scanf("%d%d", &l, &r);
 97             P a = query(l, r, 1).max_sub;
 98             printf("%d %d\n", a.first, a.second);
 99         }
100     }
101     return 0;
102 }
View Code

 

POJ2279,三角形排布是有规律的,可以验证此dp的正确性。

 1 #include <cstdio>
 2 #include <cstring>
 3 #define ll long long
 4 #define init(a, b) memset(a, b, sizeof(a))
 5 #define rep(i, a, b) for (int i = a; i <= b; i++)
 6 
 7 int K, n[6];
 8 
 9 ll solve() {
10     while (K < 5) {
11         n[++K] = 0;
12     }
13     ll dp[n[1]+1][n[2]+1][n[3]+1][n[4]+1][n[5]+1];
14     init(dp, 0);
15     dp[0][0][0][0][0] = 1;
16 
17     rep(i, 0, n[1])
18         rep(j, 0, n[2])
19             rep(k, 0, n[3])
20                 rep(s, 0, n[4])
21                     rep(t, 0, n[5]) {
22                         ll &cur = dp[i][j][k][s][t];
23                         if (i < n[1])    dp[i+1][j][k][s][t] += cur;
24                         if (j < n[2] && j < i)    dp[i][j+1][k][s][t] += cur;
25                         if (k < n[3] && k < j)    dp[i][j][k+1][s][t] += cur;
26                         if (s < n[4] && s < k)    dp[i][j][k][s+1][t] += cur;
27                         if (t < n[5] && t < s)    dp[i][j][k][s][t+1] += cur;
28                     }
29     return dp[n[1]][n[2]][n[3]][n[4]][n[5]];
30 }
31 
32 int main() {
33     while (~scanf("%d", &K) && K) {
34         rep(i, 1, K)    scanf("%d", &n[i]);
35         printf("%lld\n", solve());
36     }
37     return 0;
38 }
View Code

 

posted @ 2019-01-31 09:49  AlphaWA  阅读(186)  评论(0编辑  收藏  举报