题意
有很多小朋友,我们要给他们那糖果(我们那糖果的数量有最低和最高限制)。拿完糖果后给每一位小朋友发一颗糖果,重复这个过程直到篮子里剩余的糖果数量不足以分给所有小朋友,此时篮中剩下的糖果会作为我们的奖励,题目要求我们求出能拿到的这份奖励的最大数量。
思路:
我们可以遍历区间内每一个糖果的总数,并且开一个变量算出每种数量分糖后的剩余糖果,不断更新剩余糖果的最大值。一旦超出循环就直接跳出,最后输出最大剩余数。而且我们不需要去联想仍和算法因为这就是一道数学题
代码:
#include<bits/stdc++.h> using namespace std; int main(){ long long n,l,r;// n小朋友,最少拿l颗糖,最多拿r,颗因为这题数据范围已经达到了1e9所以要开 // longlong cin>>n>>l>>r; int sum=0; int maxn=0; for(long long i=l;i<=r;i++){ sum=i%n;// 更新最大剩余糖果数量 if(sum>maxn)maxn=sum;// 不满足条件就跳出循环 if(maxn==n-1)break; } // 输出最多能剩下的糖果 cout<<maxn; return 0; }但是,用循环的做法只能拿到90分,我们刚才说过了这是一道数学题,数学题只需要把每个变量走一遍就行,所以时间复杂度可以控制在O(1)
代码:
#include<bits/stdc++.h> using namespace std; int main(){ long long n,l,r; cin>>n>>l>>r; if(l/n!=r/n) cout<<n-1;// 两个数除以n结果不一样就输出n-1 else cout<<r%n;// 两条边界除以n商相同答案要用我们能拿糖果的最大值对n取余 return 0; }题目解释:
给定长度为 n、下标从 1 开始的数组,共有 Q 次操作,操作分为两种:
1.修改操作总数不超过 5000 次,第一种是将数组第 x 位数值改为 v并且改动是直接影响原数组
2.查询操作不改变原数组并对当前数组排序,输出原数组第 x 个元素排序后的位置。
题目思路:
我们可以用能同时存数值与初始编号的动态数组保存初始数据,再用一份副本代表当前数组的编号和数值(一定要有序),同时记录每个编号在有序列中的位置。修改数值时先从副本中移除对应元素,修改数值后找到合适位置(排序)重新插入副本,再次更新后续每个值对应位。查询时直接读取目标编号对应的位置然后输出结果就完成了。
代码:
#include <bits/stdc++.h> using namespace std; vector<pair<int, int>> a; // 存原史值和下标 vector<pair<int, int>> temp; // 维护有序序列 int n, q; int main() { cin >> n >> q; for (int i = 0; i < n; i++) { int x; cin >> x; a.push_back({x, i}); } temp = a; sort(temp.begin(), temp.end()); vector<int> pos(n); // 记录每个原始下标在副本的位置 for (int i = 0; i < n; i++) pos[temp[i].second] = i; while (q--) { int k; cin >> k; if (k == 1) { int x, y; cin >> x >> y; x--; int p = pos[x]; for (int i = p; i < temp.size(); i++) temp[i] = temp[i + 1]; temp.pop_back(); // 把数组整体往前移 for (int i = p; i < temp.size(); i++) pos[temp[i].second] = i; a[x].first = y; // 查询新的插入位置 int ispos = 0; while (ispos < temp.size() && temp[ispos] < a[x]) ispos++; temp.push_back({0, 0}); // 把数组整体往后移 for (int i = temp.size() - 1; i > ispos; i--) temp[i] = temp[i - 1]; temp[ispos] = a[x]; for (int i = ispos; i < temp.size(); i++) pos[temp[i].second] = i; } else { int x; cin >> x; x--; cout << pos[x] + 1 << endl;//因为数从0遍历的所以输出时要+1 } } return 0; }题意
依次处理 n 台机器,机器分为服务机与客户机。服务机地址不重复代表注册成功输出 OK,重复输出 FAIL,客户机地址存在已注册服务机则输出对应服务机编号,不存在输出 FAIL。
思路
我们可以记录每一个成功的服务器地址和对应编号,逐行读取每台机器的操作与地址。如果是服务机(Server),遍历已有服务机判断地址重复,重复输出 FAIL,不重复就存入容器并输出 OK;若是客户机(Client)就查找匹配的地址,找到就输出对应的地址,找不到输出 FAIL。
代码:
#include<bits/stdc++.h> using namespace std; int n; vector<pair<string,int>>s; // 储存机地址与下标 int main(){ cin>>n; for(int i=1;i<=n;i++){ string op,ad; cin>>op>>ad; bool f=0; if(op=="Server"){ // 判断地址重复 for(int j=0;j<s.size();j++){ if(s[j].first==ad){ f=1; break; } } if(f)cout<<"FAIL"<<endl; else{ s.push_back({ad,i}); cout<<"OK"<<endl; } }else{ bool f=0; // 查找对应服务机 for(int j=0;j<s.size();j++){ if(s[j].first==ad){ cout<<s[j].second<<endl; f=1; break; } } if(!f)cout<<"FAIL"<<endl; } } return 0; }