正睿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 }
View Code

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 }
View Code

T3:

  就会40pts暴力

  不会

总结:

  写代码时还是要注意一下常数,用STL的东西还是要查一下时间复杂度才行

posted on 2020-10-18 17:18  ArrogHie  阅读(117)  评论(0编辑  收藏  举报