Solved:2
02 Nonsense Time (LIS)
题意:给定一个全排列 最开始为空的 每秒中一个位置上的数出现 求每秒的LIS
题解:题解说 考虑时光倒流 倒着消掉 因为数据随机 所以期望的LIS长度为 sqrt(n) 如果每次消失掉的一个数是当前的LIS上的
就暴力重新求LIS 期望消掉 sqrt(n)个数才会修改LIS 总复杂度 nsqrt(n)logn
#include <bits/stdc++.h> using namespace std; int n; int a[50005]; int b[50005]; int d[50005]; int dp[50005]; int ans[50005]; int vis[50005]; bool vvis[50005]; int LIS() { memset(vvis, 0, sizeof(bool) * (n + 2)); int len = 0; d[0] = 0; for(int i = 1; i <= n; i++) { if(vis[i]) continue; if(a[i] > d[len]) d[++len] = a[i], dp[i] = len; else { int t = lower_bound(d + 1, d + 1 + len, a[i]) - d; d[t] = a[i]; dp[i] = t; } } int tmp = len; int now = n + 1; for(int i = n; i >= 1; i--) { if(vis[i]) continue; if(dp[i] == tmp && now > a[i]) { vvis[i] = 1; tmp--; now = a[i]; } } return len; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); memset(vis, 0, sizeof(int) * (n + 2)); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) scanf("%d", &b[i]); ans[n] = LIS(); for(int i = n; i > 1; i--) { vis[b[i]] = 1; if(vvis[b[i]]) ans[i - 1] = LIS(); else ans[i - 1] = ans[i]; } for(int i = 1; i <= n; i++) { if(i != n) printf("%d ", ans[i]); else printf("%d ", ans[i]); } } return 0; }
05 Snowy Smile (线段树)
题意:2000个物品 在坐标上 权值有正有负 求一个矩阵框起来能获得最大价值
题解:离散化坐标后 按x从小到大排序 这样枚举矩阵的左边界 依次按x往这个矩阵添物品 那么右边界也出来了
然后在这个左右区间内 用线段树维护纵坐标的最大连续子段和 每次添加完相同横坐标的物品 查询一次
然后傻傻的我 每次查询按这个左右区间来查询... 查询次数过多 妥妥爆栈了 其实按我的写法 每次更新后.. 不用查询 直接就是根节点的全局答案了
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 2005; int n; int totx, toty; struct chest { int x, y, w; int tx, ty; }a[2005]; bool cmp1(chest A, chest B) { return A.x < B.x; } bool cmp2(chest A, chest B) { return A.y < B.y; } struct node { ll sum, ssum, ls, rs; }E[MAXN << 2]; void pushup(int rt) { int lr = rt << 1; int rr = rt << 1 | 1; E[rt].ssum = E[lr].ssum + E[rr].ssum; E[rt].sum = max(E[lr].sum, E[rr].sum); E[rt].sum = max(E[rt].sum, E[lr].rs + E[rr].ls); E[rt].ls = max(E[lr].ls, E[lr].ssum + E[rr].ls); E[rt].rs = max(E[rr].rs, E[rr].ssum + E[lr].rs); } void build(int l, int r, int rt) { if(l == r) { E[rt].sum = E[rt].ssum = E[rt].ls = E[rt].rs = 0; return; } int mid = l + r >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); pushup(rt); } void update(int k, ll v, int l, int r, int rt) { if(l == r) { E[rt].ssum += v; E[rt].sum += v; E[rt].ls += v; E[rt].rs += v; return; } int mid = l + r >> 1; if(k <= mid) update(k, v, l, mid, rt << 1); else update(k, v, mid + 1, r, rt << 1 | 1); pushup(rt); } int main() { int T; scanf("%d", &T); while(T--) { totx = toty = 0; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].w); sort(a + 1, a + 1 + n, cmp2); for(int i = 1; i <= n; i++) { if(a[i].y != a[i - 1].y) a[i].ty = ++toty; else a[i].ty = toty; } sort(a + 1, a + 1 + n, cmp1); for(int i = 1; i <= n; i++) { if(a[i].x != a[i - 1].x) a[i].tx = ++totx; else a[i].tx = totx; } ll ans = 0; int las = -1; for(int i = 1; i <= n; i++) { if(a[i].tx == las) continue; build(1, toty, 1); int k; for(int j = i; j <= n; j = k) { for(k = j; k <= n && a[k].tx == a[j].tx; k++) update(a[k].ty, a[k].w, 1, toty, 1); ans = max(ans, E[1].sum); } las = a[i].tx; } printf("%lld ", ans); } return 0; }