- 吴易繁 的博客
七月暑期集训DAY03
- @ 2024-7-10 20:46:48
A. 小田的01变换
题目类型:分类讨论
思路
-
若n==2且0与1的数量一样,输出-1。
-
若0的数量等于n或1的数量等于n,输出0。
-
若0的数量==1的数量,输出2。
-
若上面的条件都不成立,输出1。
代码
#include<bits/stdc++.h> using namespace std; int main(){ freopen("change.in","r",stdin); freopen("change.out","w",stdout); int n,cnt_0=0,cnt_1=0; cin>>n; string s; cin>>s; for(int i=0;i<s.size();i++){ if(s[i]=='0') cnt_0++; if(s[i]=='1') cnt_1++; } if(n==2&&cnt_0==cnt_1) cout<<-1; else if(cnt_0==n||cnt_1==n) cout<<0; else if(cnt_0==cnt_1) cout<<2; else cout<<1; return 0; }这题在写的时候把
freopen("change.in","r",stdin); freopen("change.out","w",stdout);
写成
freopen("change.in ","r",stdin);
freopen("change.out ","w",stdout);
了
所以下次要仔细检查,一定不能再犯这种低级的错误了,所以freopen还要熟记,连空格都要记。
B. 小田滑雪
题目类型:模拟
思路
- 根据时间与路程排序,再来算总时间,最后输出答案。
- 排序可以将路程转换成时间,或将时间转换成路程,最后输出答案即可。
- 注意:最后的答案要四舍五入,可以先将答案+0.5,再转long long类型。
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("snow.in","r",stdin);
freopen("snow.out","w",stdout);
vector<int> A,B;
int n;
cin>>n;
for(int i=1;i<=n;i++){
char s;
int c;
cin>>s>>c;
if(s=='T') A.push_back(c);
else B.push_back(c);
}
sort(A.begin(),B.end());
sort(B.begin(),B.end());
A.push_back(2e9);
B.push_back(2e9);
double ans=0,dist=0,v=1;
int i=0,j=0;
while(i<A.size()-1||j<B.size()-1){
double x=1/v;
v++;
double p=dist+(A[i]-ans)*x;
if(p<B[j]) {
dist=p;
ans=A[i];
i++;
}
else{
ans=ans+(B[j]-dist)/x;
dist=B[j];
j++;
}
}
ans+=(1000-dist)/(1.0/v);
cout<<(long long)(ans+0.5);
return 0;
}
这题只把%30的数据写了,下次争取写一个AC代码。
C. 小田赶牛
题目类型:排序加模拟
思路
先结构体排序,返回a.first乘b.second<a.second乘b.first,再每次累加每头牛吃花的总数,最后输出答案即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=1e5+10;
PII a[N];
bool cmp(PII a, PII b){
return a.first*b.second<a.second*b.first;
}
int main(){
freopen("cow.in","r",stdin);
freopen("cow.out","w",stdout);
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second;
sort(a+1,a+1+n,cmp);
long long c=0,ans=0;
for(int i=1;i<=n;i++){
ans+=a[i].second*c;
c+=a[i].first*2;
}
cout<<ans;
return 0;
}
这题不知道怎么累加每头牛吃花的总数,所以就放弃了,下次不能轻易放弃。
D. 拼接最大数
题目类型:栈
思路
- 先枚举i,从第一个序列得到长度为i字典序最大的子序列,再从第二序列得到长度为k-i的字典序最大的子序列。
- 假设a的长度是n,那么也就意味着我们要抛弃n-k1个数,所以我们可以用一个单调栈来维护。
- 写一个能合并两个序列的函数,保证合并的两个序列字典序也是最大的,也就是用归并排序合并部分。
- 最后比较和之前的答案谁大,大就更新。
- 最后输出答案即可。
代码
#include<bits/stdc++.h>
using namespace std;
int cmp(vector<int> A,int ida,vector<int> B,int idb){
int len1=A.size(),len2=B.size();
while(ida<len1&&idb<len2){
if(A[ida]!=B[idb]) return A[ida]>B[idb];
ida++,idb++;
}
if(ida<len1) return 1;
else return 0;
}
vector<int> get(vector<int> A,int k){
int n=A.size();
if(n<=k) return A;
int t=n-k;
vector<int> stk;
for(int i=0;i<n;i++){
while(stk.size()>0&&stk.back()<A[i]&&t>0){
stk.pop_back();
t--;
}
if(stk.size()<k) stk.push_back(A[i]);
else t--;
}
return stk;
}
vector<int> merge(vector<int> A,vector<int> B){
int len1=A.size(),len2=B.size();
vector<int> res;
int i=0,j=0;
while(i<len1&&j<len2){
if(A[i]>B[j]) res.push_back(A[i++]);
else if(A[i]<B[j]) res.push_back(B[j++]);
else{
if(cmp(A,i,B,j)>0) res.push_back(A[i++]);
else res.push_back(B[j++]);
}
}
while(i<len1) res.push_back(A[i++]);
while(j<len2) res.push_back(B[j++]);
return res;
}
int main(){
freopen("big.in","r",stdin);
freopen("big.out","w",stdout);
int n,m,k;
cin>>n>>m>>k;
vector<int> A,B;
for(int i=1;i<=n;i++){
int x;
cin>>x;
A.push_back(x);
}
for(int i=1;i<=m;i++){
int x;
cin>>x;
B.push_back(x);
}
vector<int> ans(k,0);
for(int i=0;i<=k;i++){
int len1=i,len2=k-i;
vector<int> tmp1=get(A,len1);
vector<int> tmp2=get(B,len2);
vector<int> res=merge(tmp1,tmp2);
if(res.size()==k&&cmp(res,0,ans,0)>0) ans=res;
}
for(auto x:ans) cout<<x;
return 0;
}
这题在写的时候不知道思路,就放弃了,下次要想着将各种算法结合起来写。
E. 小W运水
题目类型:最短路
思路
这道题其实就是最短路算法模版改一点点即可,将int类型改成double类型就好了,最后输出答案即可。
代码
#include<bits/stdc++.h>
using namespace std;
int g[2010][2010];
int n,m,s,e;
double dist[2010];
bool st[2010];
void dijkstra(){
for(int i=1;i<=n;i++) dist[i]=0x3f3f3f3f;
dist[e]=100;
for(int i=1;i<=n;i++){
int t=-1;
for(int j=1;j<=n;j++)
if(!st[j]&&(t==-1||dist[j]<dist[t]))
t=j;
st[t]=1;
for(int j=1;j<=n;j++)
if(g[t][j]<200&&dist[t]/(1-g[t][j]*0.01)<dist[j]) dist[j] = dist[t]/(1-g[t][j]*0.01);
}
}
int main(){
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
cin>>n>>m;
memset(g,0x3f,sizeof(g));
while(m--){
int x,y,z;
cin>>x>>y>>z;
g[x][y]=z;
g[y][x]=z;
}
cin>>s>>e;
dijkstra();
printf("%.8lf",dist[s]);
return 0;
}
这道题我实在没想到,下一次要再好好看题。
F. WOW
题目类型:前缀和或DP
思路
如果是前缀和的话,那么我们用一个 𝑎*和𝑏数组,𝑎[𝑖]代表第 𝑖个字符前面有多少个𝑣𝑣,𝑏[𝑖]]则是后面的。那么第𝑖个字符能组成的𝑤𝑜𝑤数就是𝑎[𝑖]∗𝑏[𝑖],最后输出答案即可。
代码
前缀和
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("wow.in","r",stdin);
freopen("wow.out","w",stdout);
string s;
cin>>s;
long long a=0,b=0,c=0;
for(int i=0;i<s.size();i++){
if(s[i]=='o') b+=a;
else if(s[i-1]=='v'){
c+=b;
a++;
}
}
cout<<c;
return 0;
}
DP还没有学过,老师说以后会单独开一节课来讲DP。