标签:从后往前 include cst sum stdin pac stdout ace str
T1
这道题一开始的思路就是错误的。。
对于任意数m,我们枚举 <= m的数,实质上就是
将m的二进制(二进制表示,从前到后分别是从低位到高位表示)
的每一位1当做0,这一位之前的数所有数为任意
那么对于这道题,将负数变为0,构造一个前缀和,
从后往前枚举,当这一位是1时,我们用 前面的数全选和
后面的数只选为1的位上的数 来更新ans,然后扫完就是最终的ans
T2
二分答案 DP
二分两个数之间的差的最大值
F[i]表示i不改变的最小修改的元素个数
f[i] = min(f[j] +(i-j-1), i-1) abs(A[j]-A[i]) < 二分出来的答案*(i-j)
T3
题目本质
遇到A加y遇到B减x 求序列中相等的数的最远距离
同时可以考虑分块
T1函数最值
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int maxn = 200000; int n; char c; int a[maxn],b[maxn]; long long s[maxn]; int main() { scanf("%d",&n); for (int i = 1; i <= n; i ++){ scanf("%d", &a[i]); if (a[i] < 0) a[i] = 0; } for (int i = 1; i <= n; i ++) scanf("%1d", &b[i]); s[0] = 0; for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i]; long long ans = 0,sum = 0; for (int i = n; i >= 1; i --){ if (b[i] == 1){ ans = max(ans, sum + s[i - 1]); sum += a[i]; } } printf("%lld",ans); return 0; } /* 6 5 6 7 8 9 10 000101 */
T2函数最值2
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; int n,k; int a[2000],f[2000]; int ok(int x) { f[1] = 0; int ans = n; for (int i = 2; i<=n;i++) { f[i] = i-1; for (int j = 1; j<i;j++) if (abs(a[i]-a[j])<=((long long)x*(i-j))) f[i] = min(f[i],f[j]+(i-j-1)); ans = min(ans,f[i]+n-i); } return ans<=k; } int main() { freopen("minimum.in","r",stdin); freopen("minimum.out","w",stdout); scanf("%d%d",&n,&k); for (int i = 1; i<=n;i++) scanf("%d",&a[i]); int l = 0, r = 1000000001; for (; r-l>1; ) { int mid = (l+r)/2; if (ok(mid)) r = mid; else l = mid; } if (ok(l)) printf("%d\n",l); else printf("%d\n",r); return 0; }
T3序列
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cstdlib> #include <ctime> using namespace std; const int maxn = 200000; const int len = 400; int n, A, B,m; int a[maxn],b[maxn],l[maxn],r[maxn],lb[maxn],tot; int answer[300][300]; int rt[300][maxn], lt[300][maxn],d[maxn]; //int root[maxn*len], ll[maxn*len], rr[maxn*len],data[maxn*len]; int find(int x) { for (int l = 0, r = m; l < r;) { int mid = (l + r) / 2; if (b[mid] == x) return mid; if (b[mid]>x) r = mid; else l = mid + 1; } return -1; } int main() { double ti = clock(); freopen("sequence.in", "r", stdin); freopen("sequence.out", "w", stdout); scanf("%d%d%d", &n, &A, &B); a[0] = 0; for (int i = 1; i <= n; i++) { char c; for (scanf(" %c", &c); c != ‘A‘ && c != ‘B‘; scanf(" %c", &c)); if (c == ‘A‘) a[i] = a[i - 1] + B; else a[i] = a[i - 1] - A; } for (int i = 0; i <= n; i++) b[i] = a[i]; sort(b, b + n + 1); m = unique(b, b + n + 1) - b; for (int i = 0; i <= n; i++) { a[i] = find(a[i]); if (a[i] == -1) { printf("???\n"); return 0; } } n++; int k = n / len; for (int i = 0; i <= k; i++) { int ans = 0; tot++; for (int j = i*len; j < n; j++) { if (j%len == 0) { answer[i][j / len] = ans; } if (lb[a[j]] != tot) { lb[a[j]] = tot; l[a[j]] = j; } ans = max(ans, j - l[a[j]]); } } for (int i = 0; i < n; i++) r[i] = -1; for (int i = 0; i < n; i++) { r[a[i]] = i; if (i%len == len - 1) { int tmp = i / len; for (int j = 0; j < n; j++) rt[tmp][j] = r[j]; } } for (int i = 0; i < n; i++) l[i] = -1; for (int i = n - 1; i >= 0; i--) { l[a[i]] = i; if (i%len == 0) { int tmp = i / len; for (int j = 0; j < n; j++) lt[tmp][j] = l[j]; } } int q; scanf("%d", &q); int ans = 0; for (; q; q--) { int L, R; scanf("%d%d", &L, &R); L--; int kl = L / len, kr = R / len; ans = 0; if (kl == kr) { tot++; for (int i = L; i <= R; i++) { if (lb[a[i]] != tot) { lb[a[i]] = tot; l[a[i]] = i; } ans = max(ans, i - l[a[i]]); } } else { ans = answer[kl + 1][kr]; tot++; int tmp = min(n, (kl + 1)*len); for (int i = L; i < tmp; i++) { if (lb[a[i]] != tot) { lb[a[i]] = tot; l[a[i]] = i; ans = max(ans, rt[kr - 1][a[i]] - i); } } tmp = min(R + 1, n); for (int i = kr*len; i < tmp; i++) { if (lb[a[i]] != tot) { if (lt[kl + 1][a[i]] != -1) ans = max(ans, i - lt[kl + 1][a[i]]); } else ans = max(ans, i - l[a[i]]); } } printf("%d\n", ans); } return 0; }
标签:从后往前 include cst sum stdin pac stdout ace str
原文地址:http://www.cnblogs.com/lyqlyq/p/7774611.html