一.题意
A.有6种管子,分布在两行,管子可以旋转,问水是否能从管子的左上角流通出右下角
B.给定一个长度为m的序列x记:
排列pi(n)=[i,1,2,...,i−1,i+1,...,n],pos(p,x)表示x在排列p中的第几位
f(p)=∑m−1i=1∣pos(p,xi)−pos(p,xi+1)∣,求f(p1(n)),f(p2(n)),...,f(pn(n))
C.有一个智能机,有n条信息,屏幕只能放下k条信息,每次新来的消息总会置顶,相同的消息位置会不变,超出屏幕的消息会被挤掉,问最终屏幕上的消息数量和从顶到底的消息顺序。
D.一家商店有n个物品,价格分别为a[i] ,店员打算把所有商品价格调成相同的,但不能亏损,也不能谋暴利,求最小的价格。
E.给一个字符串,然后进行m次操作,共有两种操作:
1.将x位置的字符变成 c
2.输出 L 到 R之间字符不相同的个数
F.有一个智能机,有n条信息,屏幕只能放下k条信息(n和k数值变大),每次新来的消息总会置顶,相同的消息位置会不变,超出屏幕的消息会被挤掉,问最终屏幕上的消息数量和从顶到底的消息顺序。
二.非水题AC过程
A.首先1号和2号是一种管子x,其他的是另一种管子y,而且管子可以旋转,那么我们就可以这样想:在第一行内,x管的水可以流向y也可以流向x,但y管的水不能流向x只能流向y,之后我们从头遍历一遍给的字符串逐个判断,注意第一行的最后不能流通,换行的时候注意应该是一个B型后面跟着一个A型。
C.直接暴力用两个数组,一个储存id,一个储存id顺序,然后两个for循环嵌套,如果上扫到了id那么不执行任何操作,否则所有消息全部往后挪动一位,新消息置顶。
D.直接所有数据加起来相除算平均数,不能整除的直接加一。
三、补题情况。
B.看起来像数学题,但没能有时间去做,也没有写的思路。
E.对字符类的题目一直比较头痛,当时就直接掠过了,后来也查阅了一下这道题的相关博客,了解了大概方法。
F.数据变大了,就不能暴力解决问题了,看一些博客上写的用set来解决,不是很会用,再插一个眼,方便后来查阅。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
queue<int> q;
set<int> s;
for(int i = 1; i <= n; i++){
int id;
cin >> id;
if(!s.count(id)){ // 元素此时是否在set中
if(q.size() >= k){ // 屏幕中元素是否达到上限
int cur = q.front();
q.pop(); // pop出
s.erase(cur); // set中也删除
}
q.push(id); // 推入新元素
s.insert(id);
}
}
int m = q.size();
cout << q.size() << endl;
vector<int> v;
while(!q.empty()){
v.push_back(q.front());
q.pop();
}
reverse(v.begin(), v.end()); // 反向输出
for(int i = 0; i < m; i++){
cout << v[i] << " ";
}
return 0;
}
四、感悟
水管的题目感觉挺新鲜的,开阔了一点思路,不过主要还是复习了一下set的用法,好久没用过了,感觉生疏了许多,至于一些实在挺难的,还是停留在多看一下AC代码上。