前言
第二天的贪心的代码解答:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
ll a[N],w[N],p[N];
int T;
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> w[i];
ll fix = 0, ess = 0, res = 0;
for(int i = 1; i <= n; i ++) ess += a[i] * w[i];
for(int i = 1; i <= n; i ++)
{
fix = max(0ll , fix + (a[i] ? -1 : 1) * w[i] );
res = max(res, fix);
}
cout << ess + res << '\n';
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> T;
while(T --) solve();
return 0;
}
第三天:位运算,二分,双指针,排序内容。有点多,慢慢看。
一、位运算
基础的一共有五种:与运算,或运算,非运算,异或运算,按位取反
还有 左移 和 右移。
与或非我们都很熟悉,这里不讲了。相对于按位取反,我们可以知道-1取反是0,为什么呢?补码的知识我们知道-1在二进制中全都是1,那么取反后就是0.
左移和右移 就是二进制数位置的移动,00000011 左移 1 位 就是 00000110 , 右移一位 就是 00000001 对于溢出的部分就是直接舍弃掉。
对于异或(^)运算,我们需要知道是异或运算满足交换律和结合律,但是不满足分配律。另外对于一个结论:可能在某些题目会用到: a + b = 2 (a & b) + a ^ b。
有两道习题,放在明天讲。
二、排序
1.sort 快速排序 (去重模板)
代码如下(示例):
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
注:unique 返回的是什么呢?unique 的前提是sort ,他会把重复的元素放在整个数组后面,返回的是第一个重复元素的迭代器,可以理解为位置,那么我们erase就是消除,当然是从第一个重复元素位置进行消除,直到end。
2.桶排序
代码如下(示例):
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
using ll = long long;
const int N = 2e5 + 10;
int c[N];//桶记录的次数
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for(int i = 0; i < n; i ++)
{
int x;
cin >> x;
c[x] ++;
}
for(int i = 0; i < 2e5 + 10; i ++)
{
for(int j = 0; j < c[i]; j ++)
{
cout << i << ' ';
}
}
return 0;
}