HDU 2017 多校联合Contest 3
偷了个懒。。。好几次的多校的题没有补。。。
1003.Kanade's sum
Time Limit: 2000 MS
题意:
给出含有n个元素的数组A,A的元素是1~n的任意一个排列,求出任意区间第K的数的和。
思路:
比赛的时候是毫无头绪,后来看了题解,明白了解法。从最小的元素开始考虑,每次在他的范围内向前向后走K个,在这个区间的子区间可以确定里它是第K大的,然后将它删去,在考虑下一个,这样就得到了完美的解法。
然后我用单向链表开始写,WA了好几发,百度了别人的代码,发现是用双向链表写的,感觉双向链表对这道题的好几个点处理的很好。学习了
#include "bits/stdc++.h" using namespace std; const int maxn = 1e6; typedef long long LL; int nex[maxn], pre[maxn]; int L[maxn], R[maxn], pos[maxn]; int N, K; LL get_res(int x) { LL res = 0; int r = 0, l = 0; for (int i = x; i > 0; i = pre[i]) { //减去和前面的距离,这样对于删去节点比较好讨论 L[++l] = i - pre[i]; if (l == K) break; } for (int i = x; i <= N; i = nex[i]) { R[++r] = nex[i] - i; if (r == K) break; } for (int i = 1; i <= l; i++) { if (K - i + 1 <= r) res += (LL)L[i]*R[K-i+1]; } return res; } void del(int x) { pre[nex[x]] = pre[x]; nex[pre[x]] = nex[x]; } int main(int argc, char const *argv[]) { int T; scanf("%d", &T); while (T--) { int a; scanf("%d%d", &N, &K); for (int i = 1; i <= N; i++) {scanf("%d", &a); pos[a] = i;} for (int i = 1; i <= N; i++) {pre[i] = i-1; nex[i] = i+1;} pre[0] = 0; nex[N + 1] = N + 1; LL ans = 0; for (int i = 1; i <= N; i++) { ans += get_res(pos[i])*i; del(pos[i]); } printf("%lld\n", ans); } return 0; }
1005RXD and dividing
题意:
给你一棵树,将节点1单独拿出来,把剩下的节点分成K个部分。每个部分挑选若干条边,让包括节点1在内的每个部分都联通的,让边权最小。整棵树的价值就是每部分的价值总和。选择树的划分方式,让整棵树的价值最大。
思路:
没有证明。题解也是这个意思,统计过每条边的次数,让最大的分发肯定是尽量多的经过一个边多次。存在一个分发使得每条边经过最多不过K次。然后判断每条边走过几次。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e6 + 10; int tot = 0; int n, k; LL ans; int sz[maxn]; int head[maxn]; struct node { int to, next, val; } ; vector<node> tree[maxn]; int dfs(int u, int fa) { sz[u] = 1; for (int i = 0; i < tree[u].size(); i++) { int v = tree[u][i].to; if (v == fa) continue; sz[u] += dfs(v, u); ans += (LL)min(k, sz[v])*tree[u][i].val; } return sz[u]; } void init() { for (int i = 0; i < maxn; i++) tree[i].clear(); tot = 0; ans = 0; } int main(int argc, char const *argv[]) { while (scanf("%d%d", &n, &k) != EOF) { init(); for (int i = 0; i < n-1; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); node t; t.val = c; t.to = b; tree[a].push_back(t); t.to = a; tree[b].push_back(t); } dfs(1, -1); printf("%lld\n", ans); } return 0; }
1008 RXD and math
这道题。。。。暴力找规律。。。。函数公式不会推。。。。抽空要学莫比乌斯函数
#include "bits/stdc++.h" using namespace std; typedef long long LL; const int mod = 1e9+7; inline LL pow_mod(LL x, LL y) { LL base = x; LL res = 1; while (y) { if (y&1) res=res*base%mod; base=base*base%mod; y/=2; } return res; } int main(int argc, char const *argv[]) { LL n, k; int kcase = 0; while (scanf("%lld%lld", &n, &k) != EOF) { n %= mod; printf("Case #%d: %lld\n", ++kcase, pow_mod(n,k)); } return 0; }
1011RXD's date
签到题,检查有多少天温度大于35度
#include "bits/stdc++.h" using namespace std; int main(int argc, char const *argv[]) { int n, a; int ans = 0; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a); if (a <= 35) ans++; } printf("%d\n", ans); return 0; }