http://codeforces.com/contest/722/problem/C
题目大意:给你一个串,每次删除串中的一个pos,问剩下的串中,连续的最大和是多少。
思路一:正方向考虑问题,那么就线段树+分类讨论一下就好了,然后代码中flag表示能否转移
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha printf("haha ") const int maxn = 100000 + 5; struct Tree{ bool lf, rf; bool flag; LL val, lval, rval; }tree[maxn << 2]; int n; int b[maxn]; inline void push_up(int o){ int lb = o << 1, rb = o << 1 | 1; if (tree[lb].flag && tree[rb].flag){ tree[o].lf = tree[o].rf = true; tree[o].lval = tree[o].rval = tree[o].val = tree[lb].val + tree[rb].val; return ; } tree[o].flag = false; if (tree[lb].lf == false) tree[o].lf = false, tree[o].lval = 0; else { tree[o].lf = true; if (tree[lb].flag && tree[rb].lf) tree[o].lval = tree[lb].lval + tree[rb].lval; else tree[o].lval = tree[lb].lval; } if (tree[rb].rf == false) tree[o].rf = false, tree[o].rval = 0; else { tree[o].rf = true; if (tree[rb].flag && tree[lb].rf) tree[o].rval = tree[rb].rval + tree[lb].rval; else tree[o].rval = tree[rb].rval; } tree[o].val = max(tree[lb].val, tree[rb].val); if (tree[lb].rf && tree[rb].lf){ tree[o].val = max(tree[o].val, tree[lb].rval + tree[rb].lval); } } void build_tree(int l, int r, int o){ if (l == r) { LL val; scanf("%lld", &val); tree[o].val = tree[o].lval = tree[o].rval = val; tree[o].flag = tree[o].lf = tree[o].rf = true; return ; } tree[o].lf = tree[o].rf = tree[o].flag = true; int mid = (l + r) / 2; if (l <= mid) build_tree(l, mid, o << 1); if (r > mid) build_tree(mid + 1, r, o << 1 | 1); push_up(o); } void update(int l, int r, int pos, int o){ if (l == r && l == pos){ tree[o].val = 0; tree[o].flag = tree[o].lf = tree[o].rf = false; return ; } int mid = (l + r) / 2; if (pos <= mid) update(l, mid, pos, o << 1); if (pos > mid) update(mid + 1, r, pos, o << 1 | 1); push_up(o); } int main(){ scanf("%d", &n); build_tree(1, n, 1); for (int i = 1; i <= n; i++){ int pos; scanf("%d", &pos); update(1, n, pos, 1); printf("%lld ", tree[1].val); } return 0; }
思路二:逆向考虑,使用并查集,因为最初是0,所以我们只需要逆向考虑就好了。
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha printf("haha ") const int maxn = 1e5 + 5; LL a[maxn], b[maxn], sum[maxn], ans[maxn]; bool vis[maxn]; int n; int par[maxn]; int pfind(int x){ if (x == par[x]) return x; return par[x] = pfind(par[x]); } void unite(int x, int y){ x = pfind(x), y = pfind(y); par[x] = y; sum[y] += sum[x]; } int main(){ cin >> n; for (int i = 1; i <= n; i++) { par[i] = i; scanf("%lld", a + i); sum[i] = a[i]; } for (int i = 1; i <= n; i++) scanf("%d", b + i); LL res = 0; for (int i = n; i >= 1; i--){ ans[i] = res; if (vis[b[i] + 1]) unite(b[i], b[i] + 1); if (vis[b[i] - 1]) unite(b[i], b[i] - 1); vis[b[i]] = true; res = max(res, sum[pfind(b[i])]); } for (int i = 1; i <= n; i++) cout << ans[i] << endl; return 0; }