2022 杭电多校(3) 补题 3, 9
Cyber Language 字符串输入
签到题
题意:
读入一行小写字母组成的单词,输出每个单词的首字母
注意几点即可:
-
cin是不会吃掉回车的,所以我们需要getchar手动吃掉回车,
-
关了同步后,是不能用getchar的,需要使用
cin.get()
来吃掉回车。
代码1:关闭快读
void solve(){
cin >> t;
getchar();
while(t --){
getline(cin,st);
string ans;
for(int i= 0; i < st.size(); i++){
if(i == 0) ans += char(st[i] -'a' + 'A');
else if(st[i - 1] ==' ') ans += char(st[i] -'a' + 'A');
}
cout <<ans << endl;
st.clear();
}
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
solve();
return 0;
}
代码2:打开快读
void solve()
{
cin >> t;
cin.get();
while (t--)
{
string s;
getline(cin, s);
stringstream ss;
ss << s;
string str;
while (ss >> str)
{
char ch = str.front();
ch -= ('a' - 'A');
cout << ch;
}
cout << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
Package Delivery 贪心
题意:
有n个快递,每个快递只能在第 l 天和第 r 天取件。
每天你可以多次去驿站,但是每次只能带回最多k个物品。
现在你需要带回全部的物品,最小化去驿站的次数。
思路:
因为一天可以去拿多次快递,因此我们只需要考虑最小化去驿站次数即可。
因此对于每一个快递,我们希望在端点处理,
比赛的时候想到了一个策略:
每次选取右端点最小的点,然后同时处理右端点相同的点
-
如果有剩余快递,优先处理剩余快递。
-
处理的时候,如果当前快递的左端点大于剩余快递的右端点,则顺便把剩余快递取了。
-
每次只取K的整数倍,如果不够整数倍,则剩下不取。
-
再集中处理剩下的快递。
但是太难写,下面是正确解法:
我们可以考虑在右端点处理,因为到了右端点就不得不拿,而且右端点处能够同时拿到的快递数目是最多的。
-
如果我们今天拿的东西已经是K的整数倍的话,就没必要再考虑其他的。
-
如果不是k的整数倍,我们就补到k的整数倍(拿后面快到截至日期的快递)。
我们遍历结束时间,每次都把开始时间小于当前结束时间的物品都放入优先队列中。
代码:
void slove() {
vector<pair<int, int>>in;
vector<int>out;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
int L, R; cin >> L >> R;
in.push_back({ L,R });
out.push_back(R);
}
sort(in.begin(), in.end());
sort(out.begin(), out.end());
out.erase(unique(out.begin(), out.end()), out.end());
int idx = 0;
priority_queue<int, vector<int>, greater<int> >que;
int ans = 0;
for (int ed : out) {
while (idx < in.size() && in[idx].first <= ed) {
que.push(in[idx++].second);
}
int cnt = 0;
while (que.size() && que.top() == ed) {
cnt++;
que.pop();
}
ans += cnt / k;
if (cnt%k) {
int need = k - cnt%k;
while (que.size() && need --) {
que.pop();
}
ans++;
}
}
cout << ans << endl;
}