正睿20秋季提高十连测day6
估分:100+40+40=180
实际:100+20+40=160
T1:
签到题
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 1000010; 8 9 int n; 10 int st[N]; 11 char str[N]; 12 13 int main() 14 { 15 scanf("%d", &n); 16 scanf("%s", str + 1); 17 int ans = 0, last = 0; 18 for (int i = 1; i <= n; i++) 19 { 20 last = max(last, st[str[i] - 'a']); 21 st[str[i] - 'a'] = i; 22 ans += i - last; 23 } 24 printf("%d", ans); 25 }
T2:
写了n*k的,但实现方式不大对,常数太大了,就爆到了20
先假设每个数都是正的,负的数取反,最后减去就行
先把元素从小到大排序为s,之后用二元组(w,id)表示一个方案,w是质量和,id是当前方案考虑到了哪个元素,用一个堆来存,先把(s[1],1)存进去,每次从堆中弹出一个方案(w,id)输出,再在堆里插入两个方案(w+s[id+1],id+1)和(w+s[id+1]-s[id],id+1),可以证明这样一定可以生成前k小的方案
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 #define int long long 9 #define mp make_pair 10 11 const int N = 500010; 12 13 int n, k; 14 int a[N], ans[N], res, cnt; 15 16 priority_queue<pair<int, int> >q; 17 18 signed main() 19 { 20 scanf("%lld%lld", &n, &k); 21 for (int i = 1; i <= n; i++) 22 { 23 scanf("%lld", &a[i]); 24 if (a[i] < 0) res += a[i], a[i] = -a[i]; 25 } 26 sort(a + 1, a + 1 + n); 27 28 ans[++cnt] = res; 29 q.push(mp(-a[1], 1)); 30 for (int i = 1; i < k; i++) 31 { 32 int x = -q.top().first, y = q.top().second; 33 q.pop(); 34 35 ans[++cnt] = res + x; 36 if (y == n) continue; 37 38 q.push(mp(-(x + a[y + 1]), y + 1)); 39 q.push(mp(-(x - a[y] + a[y + 1]), y + 1)); 40 } 41 for (int i = 1; i <= cnt; i++) printf("%lld\n", ans[i]); 42 }
T3:
就会40pts暴力
不会
总结:
写代码时还是要注意一下常数,用STL的东西还是要查一下时间复杂度才行