Day3算法训练(简写单词,dd爱框框,3-除2!)
1.简写单词

这是一道简单的模拟题。(模拟题最重要的是题意,一定要把题目搞清楚)
本题对我来说的收获就是输入部分,因为cin遇到空格就会终止,所以对于输入一行带有空格的字符串我想到的是getline,【用法:读取一整行字符串,包含空格,直到遇到换行符 '\n' 为止(换行符会被读取但不包含在结果中)。】其次,就是把整个字符串切割遍历的部分,有点犹豫size()的用法【在 C++ 中,std::string 的 size() 方法返回的是字符串中有效字符的数量(不包含字符串末尾的终止符 '\0'),但包含字符串中的空格。例如,输入hello world,n=11;包括空格但不包括‘\0’】最后,toupper是将小写字母转化成大写字母,头文件是<cctype>;tolower是将大写字母转化为小写;isalpha:判断字符是否是字母(a-z;A-Z);isdigit:判断字符是否为数字(0-9);isspace:判断字符是否为空白字符(空格,换行\n,制表符\t);islower:判断字符是否为小写字母;isupper判断字符是否为大写字母。
#include <iostream>
#include <string>
#include <cmath>
using namespace std;int main() {string s;string ret;getline(cin,s);int n=s.size();ret.push_back(toupper(s[0]));for(int i=0;i<n;i++){if(s[i]==' '){ret.push_back(toupper(s[i+1]));}}cout<<ret<<endl;return 0;}看过题解,又有了新的输入操作,即while(cin>>s),对于string 类型数据,cin的读取规则为跳过开头的空白字符,同事遇到空白字符停止,这保证了每次循环只读取一个单词,同时,cin的返回值室友输入的正确性决定的,如果正确输入,则返回true,如果非法输入或者停止输入,则返回false.
同时,也要牢记大小写字母的ASIIC码表。
#include <iostream>
#include <string>
#include <cmath>
using namespace std;int main() {string s;while(cin>>s)//自动跳过空格{if(s[0]<='z'&&s[0]>='a') cout<<(char)(s[0]-32);else cout<<s[0];}return 0;}2.dd爱框框

我的思路:用i遍历一遍数组,用prev1和prev2两个指针来分别指向左右两侧数组下标。prev1先指向1,prev2跟着i向右移动,每次移动记录下sum,再判断sum是否大于等于x,如果不是,i和prev2继续往后移动,如果是!!关键核心代码(用ret来记录prev1和prev2的最小距离,如果小于之前的ret,【就是这里卡住了,就是既要记录ret最小时的prev1,同时prev1又要向后移动找后续是否有更小的ret,所以感觉很乱,不知道应该先写那个语句,新设的变量应该初始化在哪个位置】)----------解决我的困扰的最主要方法就是再用两个变量来记录原来的prev1,prev2!!!这样的话,就算prev1和prev2一直在更新,也不会影响我们已经存好的最优解
题解:滑动窗口问题【特点:同向双指针,同时有一个必要条件才能用此方法,就是数组里的是必须是>0的才能保证越往后越大】
需要解决的问题:1.进窗口:sum+=arr[right] 2.判断:sum>=x 3.出窗口:sum-=arr[left] 4.更新结果:right-left+1<retlen
以后写这种题要尽量按照上述的步骤往后写。
#include <vector>
#include <cmath>
using namespace std;const int N=1e7+10;int arr[N];
int n,x;//为什么这里要变成全局变量?因为优势后写函数的时候可以不用传参直接用很方便int main()
{cin>>n>>x;for(int i=1;i<=n;i++) cin>>arr[i];int left=0,right=0,sum=0;int retLen=N,retLeft=-1,retRight=-1;while(right<=n){sum+=arr[right];while(sum>=x){if(right-left+1<retLen){retLeft=left;retRight=right;retLen=right-left+1;}sum-=arr[left++];}right++;}cout<<retLeft<<" "<<retRight<<endl;return 0;
}3.除2!

我的思路:错误点在于没有想到堆!!
题解:模拟+贪心+堆
模拟实现一个堆,每次拿出对顶元素砍一半,砍完之后如果是偶数就放回去,
// #include <iostream>
// #include <vector>
// #include <algorithm>
// const int N=1e5+10;
// int arr[N];
// using namespace std;
// int main()
// {
// int n,k;
// cin>>n>>k;
// for(int i=0;i<n;i++)cin>>arr[i];
// int sum1=0,sum2=0,sum=0;
// vector<int> brr;
// for(int i=0;i<n;i++)
// {
// if(arr[i]%2) sum1+=arr[i];
// else {brr.push_back(arr[i]);}
// }
// //brr里全是偶数,对其进行排序
// while(k>0&&!brr.empty())
// {
// sort(brr.begin(), brr.end(), greater<int>());
// brr[0]/=2;
// if(brr[0]%2){
// sum1+=brr[0];
// brr.erase(brr.begin());
// }
// k--;
// }
// for(int e:brr)
// {
// sum2+=e;
// }
// sum=sum1+sum2;
// cout<<sum<<endl;// return 0;
// }
#include <iostream>
#include <queue>using namespace std;typedef long long ll;ll n,k;
priority_queue<ll> heap;int main()
{cin>>n>>k;ll sum=0,x;while(n--){cin>>x;sum+=x;if(x%2==0) heap.push(x);}while(heap.size()&&k--){ll t =heap.top()/2;heap.pop();sum-=t;if(t%2==0) heap.push(t); }cout<<sum<<endl;return 0;
}4.小结
这篇考察了堆,滑动窗口,贪心,模拟。课后要多加练习。认真读题,理清思路,对于那道题要用哪个算法来解还是不够敏感,要加强模块训练,特别注意,
typedef long long ll;
const int N 1e10;
如果要写函数啥的最好把要输入的变量和数组设为全局变量;
有时候也不是非要写一个完整数组不可的,或许可以用变量直接解决了问题,就不用再开辟完整数组空间了 。
fighting!!!
