ABC 377 Review
ABC 377 Review
A
模拟题,但是好像wa了一发,有点幽默
Code
#include<bits/stdc++.h>
using namespace std;
char s[5];
int main()
{
for(register int i=1;i<=3;++i)s[i]=getchar();
sort(s+1,s+4);
if(s[1]=='A'&&s[2]=='B'&&s[3]=='C')cout<<"Yes";
else cout<<"No";
return 0;
}
B C
都是模拟题,甚至但是C题还是需要注意一下细节,去掉算重的答案就可以了。
CodeB
#include<bits/stdc++.h>
using namespace std;
char mp[10][10];
int n=8;
inline void input()
{
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
cin>>mp[i][j];
}
inline bool check(int x,int y)
{
for(register int i=1;i<=n;++i)
{
if(i==x)continue;
if(mp[i][y]=='#')return 0;
}
for(register int j=1;j<=n;++j)
{
if(j==y)continue;
if(mp[x][j]=='#')return 0;
}
return 1;
}
inline int calc()
{
int ans=0;
for(register int i=1;i<=n;++i)
{
for(register int j=1;j<=n;++j)
{
if(mp[i][j]=='#')continue;
if(check(i,j))ans++;
}
}
return ans;
}
int main()
{
input();
cout<<calc();
return 0;
}
CodeC
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
inline bool valid(int x,int y)
{
return 1<=x&&x<=n&&1<=y&&y<=n;
}
map<int,map<int,int>> vis;
int c1[8]={2,1,-1,-2,-2,-1,1,2},c2[8]={1,2,2,1,-1,-2,-2,-1};
inline void calc(int x,int y,int &ans)
{
for(register int t=0;t<8;++t)
{
int tx=x+c1[t],ty=y+c2[t];
if(!valid(tx,ty))continue;
if(!vis[tx][ty])ans--,vis[tx][ty]=1;
}
}
inline void solve()
{
cin>>n>>m;
int x,y;
long long ans=n*n-m;
for(register int i=1;i<=m;++i)
{
scanf("%lld%lld",&x,&y);
if(vis[x][y])ans++;
vis[x][y]=1;
calc(x,y,ans);
}
cout<<ans;
}
signed main()
{
solve();
return 0;
}
D
太经典了,一卡题就坐牢,这次坐了一个小时的牢。
分析
其实还是想到了算法的。考虑如果一个左端点固定的话,那么它的右端点可以怎么取?
那么很显然地可以想到如下算法流程:
从 \(1-m\) 枚举左端点,每次经过了一个左端点,就把这个左端点和它对应的右端点一起删除掉。
那么假设当前枚举到了 \(x\) ,我们最多能取的右端点,肯定是当前还存在的最小右端点 \(-1\) 。
这样我们在这个位置上的 \(ans\) 就是 \((Min_r-1)-x+1=Min_r-x\) 。
细节
如果当前的区间已经被全部删没了,那么实际上还是可以产生答案,所以我们还要插入一个 \(m+1\) 的右端点。
左右端点都是可重的,因此对于每一个左端点,我们都要开一个vector来记录有哪些右端点与其对应,才可以方便删除。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e5+10;
template<typename T>inline void re(T &x)
{
x=0;
int f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
x*=f;
}
int n,m;
multiset<int>visl,visr;
inline void solve()
{
re(n),re(m);
vector<int> Rl[m+1];
for(register int i=1,l,r;i<=n;++i)
{
re(l),re(r);
visl.insert(l);
visr.insert(r);
Rl[l].push_back(r);
}
visr.insert(m+1);
long long ans=0;
for(register int x=1;x<=m;++x)
{
while(visl.size()&&visl.count(x-1))
{
visl.erase(visl.lower_bound(x-1));
visr.erase(visr.lower_bound(Rl[x-1][Rl[x-1].size()-1]));
Rl[x-1].pop_back();
}
int findr=*visr.upper_bound(0);
ans+=findr-x;
}
cout<<ans;
}
signed main()
{
solve();
return 0;
}
总结
又强化了set的使用技巧,学到了可重点对的记录方式。
最重要的是想到了就去写,代码能力就是不断锻炼出来的。
没有思路就换个角度,或者是开另外一道题。
为什么要练,为什么要写?
引用一句让我幡然悔悟的话:
“练了不一定写的出来正解,不练一定写不出来正解”
本文来自博客园,作者:Hanggoash,转载请注明原文链接:https://www.cnblogs.com/Hanggoash/p/18508545