比赛链接:ABC339
简单题。但是相比于之前的A题来说还是变难了。直接上代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
string str;
cin>>str;
int pos=-1;
for(int i=1;i<str.size();i++){
if(str[i]=='.')
pos=i;
}
cout<<str.substr(pos+1)<<endl;
return 0;
}
纯纯的模拟题。
#include <bits/stdc++.h>
using namespace std;
const int dx[4]={-1,0,1,0};
const int dy[4]={0,1,0,-1};
int main(){
int n,m,k;
cin>>n>>m>>k;
vector<vector<char>> grid(n,vector<char>(m,'.'));
int x=0,y=0,dir=0;
while(k--){
if(grid[x][y]=='.'){
grid[x][y]='#';
dir=(dir+1)%4;
x+=dx[dir];
y+=dy[dir];
}
else{
grid[x][y]='.';
dir=(dir+3)%4;
x+=dx[dir];
y+=dy[dir];
}
x+=n;
y+=m;
x%=n;
y%=m;
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cout<<grid[i][j];
}
return 0;
}
贪心。我们先假设初始有0人,找到公交车每时每刻人数的最小值即记为mn。如果mn<0,则这个时刻公交车上有mn人,因为是负数了,所以初始应该至少有mn人,才能导致现在不为负数个人;否则初始公交车上可以有0人。代码很简单。
#include <bits/stdc++.h>
using namespace std;
int main(){
long long n,a,b=0,mn=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>a;
b+=a;
min=min(mn,b);
}
cout<<b-min<<endl;
return 0;
}
记得开long long哦。
思维难度不大,但是很难写。其实就是简单地广搜,让两个人一起动就行了。
#include <bits/stdc++.h>
using namespace std;
const int dx[5]={0,1,-1,0,0};
const int dy[5]={0,0,0,1,-1};
int que[maxn*maxn*maxn*maxn][5];
bool vis[maxn][maxn][maxn][maxn];
char grid[maxn][maxn];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%s",grid[i]+1);
for(int j=1;j<=n;j++){
if(grid[i][j]=='P'){
if(!que[1][1]){//遇到玩家
que[1][1]=i;//行
que[1][2]=j;//列
}
else{
que[1][3]=i;
que[1][4]=j;
}
}
}
}
int head=0,tail=1;
while(head<tail){//bfs
head++;
if(que[head][1]==que[head][3] && que[head][2]==que[head][4]){
cout<<que[head][0];
return 0;
}
for(int i=1;i<=4;i++){
int x1=que[head][1]+dx[i];
int x2=que[head][3]+dx[i];
int y1=que[head][2]+dy[i];
int y2=que[head][4]+dy[i];
if(x1<1 || x1>n || y1<1 || y1>n || grid[x1][y1]=='#'){
x1-=dx[i];
y1-=dy[i];
}
if(x2<1 || x2>n || y2<1 || y2>n || grid[x2][y2]=='#'){
x2-=dx[i];
y2-=dy[i];
}
if(vis[x1][y1][x2][y2])
continue;
que[++tail][1]=x1;
que[tail][2]=y1;
que[tail][3]=x2;
que[tail][4]=y2;
que[tail][0]=que[head][0]+1;
vis[x1][y1][x2][y2]=true;
}
}
cout<<-1<<endl;
return 0;
}
由于数据很小,所以即使这样也不会MLE。
题目说求最长子序列,就知此题事dp。我们令表示前i个数的最大答案,可得的状态转移方程:()
但是肯定超时。所以线段树优化即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn=500005;
struct node{
int l;//左极限
int r;//右极限
int v;//最大值
}segtree[maxn*4];//线段树
int A[maxn],dp[maxn];
void build(int l,int r,int u){//构建线段树
segtree[u].l=l;
segtree[u].r=r;
segtree[u].v=0;
if(l==r)
return;
int mid=(l+r)>>1;
build(l,mid,u<<1);
build(mid+1,r,(u<<1)+1);
}
int get_max(int l,int r,int u){//求最大值
if(l<=segtree[u].l && segtree[u].r<=r)//在查询部分内
return segtree[u].v;
int mid=(segtree[u].l+segtree[u].r)>>1;
int res=0;
if(l<=mid)//查询的左极限覆盖到了左子树部分
res=max(get_max(l,r,u<<1),res);
if(r>mid)//查询的右极限覆盖到了右子树部分
res=max(get_max(l,r,(u<<1)+1),res);
return res;
}
void modify(int k,int l,int u){
segtree[u].v=max(segtree[u].v,k);//更新线段树
if(segtree[u].l==segtree[u].r)
return;
int mid=(segtree[u].l+segtree[u].r)>>1;
if(l<=mid)//在左子树
modify(k,l,u<<1);
if(l>mid)//在右子树
modify(k,l,(u<<1)+1);
}
int main(){
int N,D;
cin>>N>>D;
int mn=INT_MAX,mx=INT_MIN;
for(int i=0;i<N;i++){
cin>>A[i];
mn=min(mn,A[i]);
mx=max(mx,A[i]);
}
build(mn,mx,1);
for(int i=0;i<n;i++){//动态规划(类似LIS)
dp[i]=1;//初始化
dp[i]+=get_max(max(mn,A[i]-D),min(mx,A[i]+D),1);
insert(dp[i],A[i],1);//更新线段树
}
int ans=-1;//记得初始化为INT_MIN
for(int i=0;i<n;i++)
ans=max(ans,dp[i]);
cout<<ans<<endl;
return 0;
}
以上就是本期的全部内容了。我们下期再见!
友情提醒:本期的全部代码都有问题,请不要无脑Ctrl C+Ctrl V