10062. Majority Opinion
思路分析
这道题就是一道思维题,这种题需要刻意练习,形成一定的思维模式用之前学过算法的原理去思考问题,而不是一味考验某一种算法的应用。
这道题就需要思考的是什么情况可以让这个奶牛爱吃同一种干草,分析如果大于半的奶牛喜欢吃同一种干草那么这些奶牛就会都喜欢吃这种干草,那么先从规模最小的3个奶牛思考问题(因为大于一般的奶牛数量最少也要三头)那么观察规律可得,bba,或者是bab,或者是abb三种情况可以满足条件,再分析一下,bba,和abb都是有两头喜欢吃一种干草的奶牛并列,而bab是两头喜欢吃一种干草的奶牛中间隔了一头奶牛,所以规律就推出来了,因为接下来不管是几头奶牛绝对会被同化。
AC代码
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 1e6+10;
const int M = 1e2;
int a[N],s[N];
vector<int> g;
int main(){
int t; cin >> t;
while(t--){
int n; cin >> n;
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
//abb或bba型
if((a[i] == a[i+1] || a[i] == a[i-1]) && !s[a[i]]){
g.push_back(a[i]);
s[a[i]] = 1;
}
//bab型
if((a[i] == a[i+2] || a[i] == a[i-2]) && !s[a[i]]){
g.push_back(a[i]);
s[a[i]] = 1;
}
}
sort(g.begin(),g.end());
if(g.empty()) cout << -1 << endl;
else{
for(int i = 0; i < g.size(); i++){
cout << g[i] << " ";
}
cout << endl;
}
memset(s,0,sizeof(s));
memset(a,0,sizeof(a));
g.clear();
}
return 0;
}
10063. Cannonball
思路分析
这本来就是一道简单的模拟题,但是你如果纯模拟就会超时,所以需要一点优化,注意题目中的一句话,如果 Bessie
弹跳无限长的时间或直到她离开数轴,她会击破多少个炮击目标,所以有可能他会在两个跳板之间来回跳,所以我们需要判断一下如果他跳的次数超过3*1e5(因为跳板就1e5那么长,所以你跳同一个地方3次多肯定是反复横跳了,直接结束)
代码
#include<iostream>
using namespace std;
const int N = 1e5+10;
typedef pair<int,int> PII;
int n,s,cnt = 0,st[N];
PII a[N];
int main(){
cin >> n >> s;
for(int i = 1; i <= n; i++){
cin >> a[i].first >> a[i].second;
}
int v = 1,ff = 1,t = 0; //t是看跳跃次数的
while(s <= n && s > 0 && t < 1e5*5){
t++;
if(a[s].first == 0){
if(ff < 0) ff = 1;
else ff = -1;
v += a[s].second;
}
else{
if(!st[s]){
if(a[s].second <= v){
cnt++;
st[s] = 1;
}
}
}
s += v*ff;
}
cout << cnt << endl;
return 0;
}
10064. Balancing Bacteria
思路分析
题目用到的算法是二分,两次二分,但是本质上是一道思维题,他每次喷洒药水是一个等差数列,所以就只需要把他进行二次差分操作,统计出来不为零的的绝对值的草相加,就为喷洒草药的次数。可能有点难理解,可以看一下luogu上这道题的题解:登录 - Luogu Spilopelia
代码
#include <iostream>
#include <cmath>
using namespace std;
const int N = 1e6;
long long n,a[N],s[N],s2[N],ans;
//别忘了long long
int main(){
cin>>n;
for(int i = 1;i<=n;i++){
cin>>a[i];
s[i]=a[i]-a[i-1];
s2[i]=s[i]-s[i-1];
ans+=abs(s2[i]);
}
cout<<ans;
}
10065. Cow Party S
思路分析
第四题是一个图论的模版题目,所以我们只需要背板子即可。(当时没做出来,板子掌握不熟练,上午讲下午就考我也真服了)Dijkstra最短路径算法,但是需要注意的,在求每个农场到x的距离并不等于x到每个农场的距离(题目让求来回),因为这是有向图,所以就需要反向建边(比如是a-b的边我们就建b-a的边)然后再跑一遍Dijkstra算法即可
代码
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e5+10;
typedef pair<int,int> PII;
struct Node{
int a,b,c;
} tmp[N];
int h[N],e[N],ne[N],dist[N],s[N],w[N],idx,n,m,sum[N];
void add(int a, int b,int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx;
idx++;
}
void dijkstra(int st){
memset(dist,0x3f,sizeof dist);
memset(s,0,sizeof s);
priority_queue<PII,vector<PII>,greater<PII> > q;
dist[st] = 0;
q.push({dist[st],st});
while(!q.empty()){
auto t = q.top();
q.pop();
int k = t.second,dis = t.first;
if(s[k]) continue;
s[k] = 1;
for(int i = h[k]; i != -1; i = ne[i]){
int j = e[i];
if(dis+w[i] < dist[j]){
dist[j] = dis+w[i];
q.push({dist[j],j});
}
}
}
for(int i = 1; i <= n; i++){
sum[i] += dist[i];
}
}
int main(){
memset(h,-1,sizeof h);
int x;
cin >> n >> m >> x;
for(int i = 1; i <= m; i++){
int a,b,c; cin >> a >> b >> c;
add(a,b,c);
tmp[i] = {a,b,c};
}
dijkstra(x);
memset(h,-1,sizeof h);
idx = 0;
for(int i = 1; i <= m; i++){
add(tmp[i].b,tmp[i].a,tmp[i].c);
}
dijkstra(x);
int mx = -1e9;
for(int i = 1; i <= n; i++){
mx = max(sum[i],mx);
}
cout << mx << endl;
return 0;
}
总结
这是暑假集训第二次考试总体成绩不理想,但是要继续加油,出现的问题主要是算法模版掌握不牢,所以要理解性记忆算法模版,以及思维题做的不好,要多练习思维题,提高逻辑思维