#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 }
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 }
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 }
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 }