Codeforces Global Round 19
B.
这次比赛暴力写的多,没有想到正解,对于这种复杂的情况一定是有结论可以让题目变得简单的。对A来讲如果已经排了序,那么一定是no否则 说明存在一个点a[i] > a[j], i < j或者让a[i] < a[j] i > j对于第一种情况一定是YES,对于第二种情况我们可以让j - 1也是天然的非减。说明如果没有排好序,就一定是YES 对于B考虑贪心,因为我们需要让值尽可能大,我们分尽可能多的段,也就是1个数字一个段,除0意外的数都没有贡献,只有0对答案会有1的贡献。然后考虑包含0的所有区间数为(i + 1) * (n - i) * (1 + (a[i] == 0));
#includeusing namespace std;#define rep(i,l,r) for(int i=(l);i<=(r);i++)#define per(i,l,r) for(int i=(l);i>=(r);i--)#define ll long long#define pii pair#define mset(s,t) memset(s,t,sizeof(t))#define mcpy(s,t) memcpy(s,t,sizeof(t))#define fir first#define pb push_back#define sec second#define sortall(x) sort((x).begin(),(x).end())inline int read () { int x = 0, f = 0; char ch = getchar(); while (!isdigit(ch)) f |= (ch=='-'),ch= getchar(); while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return f?-x:x;}template void print(T x) { if (x < 0) putchar('-'), x = -x; if (x >= 10) print(x/10); putchar(x % 10 + '0');}#define int long longconst int N = 2e5 + 10;int n;int f[N];int a[N], b[N];int sum;void solve() { cin >> n; memset(f, 0, sizeof f); sum = 0; for (int i = 1; i<= n ;i ++) { cin >> a[i]; sum += a[i]; } for (int i = 1; i<= n ;i ++) { cin >> b[i]; sum += b[i]; } f[0] = 1; for (int i = 1; i<= n; i ++) { int ndp[N] = {0}; for (int j = 0; j <= sum; j ++) { if (f[j]) { ndp[j + a[i]] = ndp[j + b[i]] = 1; } } memcpy(f, ndp,sizeof f); } int ans = sum * sum; for (int i = 0; i <= sum; i ++) { if (f[i]) ans = min (ans, i * i + (sum - i) * (sum - i)); } for (int i = 1; i <= n; i ++) { ans += (a[i] * a[i] + b[i] * b[i]) * (n - 2); } cout << ans << endl; }signed main () { int t; cin >> t; while (t --) solve(); }
01背包问题,通过背包判断哪些体积是可行的。然后推式子可以发现如图 一一部分是不变的,然后让一部分取最小。这是个经典技巧。通过遍历取全局最小
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~