本蒟蒻第一次写上海月赛题解,初测500分就屁颠屁颠跑来CSDN写题解了
T1 求和问题
这道水题只要从用一个值储存大小,从1~n遍历、更新就好了,这么“难”的题目,直接贴代码:
#include <bits/stdc++.h>
using namespace std;
long long n,a[200005],sum,ans;
int main() {
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++) {
sum+=a[i];
if(sum>=0) ans=i;
}
cout<<ans;
return 0;
}
T2 得分排名
直接sort+比较函数,STL就是香
#include <bits/stdc++.h>
using namespace std;
struct student{
int num,val;
}a[200005];
bool cmp(student a,student b) {
if(a.val==b.val) return a.num<b.num;
return a.val>b.val;
}
int n;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i].val);
a[i].num=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) cout<<a[i].num<<"\n";
return 0;
}
用优先队列也不错,STL太舒服了
T3 录制节目(一)
这道题目应该是在Internet上有类似的题目的,我想到了二分(即O(nlogn)),这道题我的思路就是排序+dp+二分,众所周知,一个节目要么录制,要么不录制
1、录制
若要录制,则转移过来的j节目必须符合:
①j<=i
②j的结束时间小于i的开始时间
因为结束时间是有序的,所以可以排序预处理,通过二分O(logn)的时间复杂度求得j
dp[i]可取dp[j]+1
2、不录制
因为i节目之前的节目结束时间都小于i,所以i节目不录制的最优策略是取前面所有dp的最大值,即dp[i]=max(dp[i-1],dp[i-2],...,dp[1]),因为dp[i-1]已是最优,囊括了前面所有的最大值,则dp[i]可取dp[i-1],,所以前面的无值需再考虑
因此转移方程是dp[i]=max(dp[j]+1,dp[i-1);
j通过二分求得
上代码
#include <bits/stdc++.h>
using namespace std;
struct node{
int s,t;
}x[200005];
inline bool cmp(node a,node b) {
if(a.t==b.t) return a.s<b.s;
return a.t<b.t;
}
int Find(int i) {
int l=1,r=i-1,ans=0;
while(l<=r) {
int mid=(l+r)/2;
if(x[mid].t<=x[i].s) {
ans=mid;
l=mid+1;
} else r=mid-1;
}
return ans;
}
int n,dp[200005],ans;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d%d",&x[i].s,&x[i].t);
}
sort(x+1,x+n+1,cmp);
for(int i=1;i<=n;i++) {
int k=Find(i);
dp[i]=max(dp[i],dp[k]+1);
dp[i]=max(dp[i],dp[i-1]);
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
T4 子集归零
这题挺简单的,直接dfs暴力就过了,2的22次方也就百万级别
#include <bits/stdc++.h>
using namespace std;
int ans,n,k[30];
inline void dfs(int sum,int i) {
if(i==n-1) {
if(sum==0) ans++;
if(sum+k[i]==0) {
sum=0;
ans++;
}
return;
}
dfs(sum,i+1);
dfs(sum+k[i],i+1);
}
int main() {
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&k[i]);
dfs(0,0);
cout<<ans;
return 0;
}
T5 池塘计数
这题dfs的经典题了,让dfs走一下标记一下就好了,没什么坑点和难点,代码:
#include <bits/stdc++.h>
using namespace std;
int n,m,dx[]={1,-1,0,0},dy[]={0,0,1,-1},ans;
char mp[205][205];
void dfs(int x,int y) {
mp[x][y]='#';
for(int i=0;i<4;i++) {
int tx=x+dx[i];
int ty=y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&mp[tx][ty]=='.') dfs(tx,ty);
}
return;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
cin>>mp[i][j];
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(mp[i][j]=='.') {
dfs(i,j);
ans++;
}
}
}
cout<<ans;
return 0;
}
总体来说,这次的上海月赛丙组比较水,代码仅供学习,copy后果自负