文章目录
- [A. Quintomania](#A. Quintomania)
- [B. Startup](#B. Startup)
- [C. Anya and 1100](#C. Anya and 1100)
- [D. I Love 1543](#D. I Love 1543)
- [E. Reverse the Rivers](#E. Reverse the Rivers)
https://codeforces.com/contest/2036
A. Quintomania
思路
签到题,直接模拟即可
code
cpp
void solve(){
int n;cin >> n;
for(int i=1;i<=n;++i) cin >> a[i];
for(int i=2;i<=n;++i){
if(abs(a[i]-a[i-1])==5 || abs(a[i]-a[i-1])==7)
continue;
else{
cout << "NO" << endl;
return ;
}
}
cout << "YES" << endl;
return ;
}
B. Startup
思路
考点:排序
用桶标记的思维将k个数存入到数组中,再将数组进行降序排序,最后取前n个数即可
code
cpp
const int N=1e6+5;
int a[N];
void solve(){
int n,k;
cin >> n >> k;
int ans=0,mx=0;
int s=max(n,k);
for(int i=1;i<=s;++i) a[i]=0;
for(int i=1;i<=k;++i){
int x,y;
cin >> x >> y;
a[x]+=y;
}
sort(a+1,a+1+k,greater<int>());
for(int i=1;i<=n;++i) ans+=a[i];
cout << ans << endl;
return ;
}
C. Anya and 1100
思路
考点:模拟
先统计字符串中"1100"的个数 ,对于q次询问,每次改变1个字符,通过观察不难发现:
改变的这一个字符只影响它前面3个字符和后面3个字符 ,因此我们只需要暴力循环这7个字符即可
先不替换这个字符,减去这7个位置的"1100"的个数
替换这个字符,加上这7个位置的"1100"的个数
判断 c n t cnt cnt 个数是否大于0,满足输出YES
反之输出NO
code
cpp
void solve(){
string s;cin >> s;
int q;cin >> q;
int cnt=0,n=s.size();
for(int i=0;i<=n-4;++i){
if(s[i]=='1' && s[i+1]=='1' && s[i+2]=='0' && s[i+3]=='0')
cnt++;
}
while(q--){
int x;
char v;
cin >> x >> v;
x--;
for(int i=max(0ll,x-4+1);i<=x;++i){
if(s[i]=='1' && s[i+1]=='1' && s[i+2]=='0' && s[i+3]=='0')
cnt--;
}
s[x]=v;
for(int i=max(0ll,x-4+1);i<=x;++i){
if(s[i]=='1' && s[i+1]=='1' && s[i+2]=='0' && s[i+3]=='0')
cnt++;
}
if(cnt>0) cout << "YES" << endl;
else cout << "NO" << endl;
}
return ;
}
D. I Love 1543
思路
考点:模拟
对于每一个外层,我们将这些数存入到数组中
注意:需要多存入3个数,例如:
5 4
1 3
假设我们从5开始读取,那么数组包含的数为 5 4 3 1 ,显然数组中并没有连续的1543
可是对于这个样例来说,它是有1个连续的1543
观察数组,这个1在数组的末位
显然我们还需要在这个数组中多添加3个数,因此最终的数组为 5 4 3 1 5 4 3
统计数组中连续的1543,最后输出即可
code
cpp
const int N=1e3+5;
char a[N][N];
void solve(){
int n,m;
cin >> n >> m;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
cin >> a[i][j];
}
int ans=0;
int t=min(n,m);
t/=2;
int l=1;
while(t--){
vector<char> v;
for(int i=l;i<=m;++i) v.push_back(a[l][i]);
for(int i=l+1;i<=n;++i) v.push_back(a[i][m]);
for(int i=m-1;i>=l;--i) v.push_back(a[n][i]);
for(int i=n-1;i>l;--i) v.push_back(a[i][l]);
int k=3;
for(int i=l;i<=m;++i){
if(k){
v.push_back(a[l][i]);
k--;
}
else break;
}
for(int i=l+1;i<=n;++i){
if(k){
v.push_back(a[i][m]);
k--;
}
else break;
}
for(int i=m-1;i>=l;--i){
if(k){
v.push_back(a[n][i]);
k--;
}
else break;
}
// for(auto i : v) cout << i << " ";
// cout << endl;
for(int i=0;i<=v.size()-4;++i){
if(v[i]=='1'){
if(v[i+1]=='5' && v[i+2]=='4' && v[i+3]=='3') ans++;
}
}
l++,m--,n--;
}
cout << ans << endl;
return ;
}
E. Reverse the Rivers
思路
考点:二分
首先预处理 a [ i ] [ j ] ∣ = a [ i − 1 ] [ j ] a[i][j]|=a[i-1][j] a[i][j]∣=a[i−1][j]
然后将n行k列转换为k行n列,即 b [ j ] [ i ] = a [ i ] [ j ] ; b[j][i]=a[i][j]; b[j][i]=a[i][j];
对于q次询问,首先定义左右边界 ,即 l = 1 , r = n l=1,r=n l=1,r=n
对于m次询问:
- 如果o为 < < < ,我们可以用lower_bound函数在 b [ k ] b[k] b[k] 中找出大于等于 c c c 的第一个值的下标
那么这个下标(包过这个下标)之后的值都不在我们要找的范围中
将这个下标赋值给x, r = x − 1 r=x-1 r=x−1 ,同小取小,我们要找最小的下标,那么 r = m i n ( r , x − 1 ) r=min(r,x-1) r=min(r,x−1) - 反之,我们可以用upper_bound函数在 b [ k ] b[k] b[k] 中找出大于 c c c 的第一个值的下标
那么这个下标之前的值都不在我们要找的范围中
将这个下标赋值给x, l = x l=x l=x ,同大取大,我们要找最大的下标,那么 l = m a x ( l , x ) l=max(l,x) l=max(l,x)
最后判断如果 l < = r l<=r l<=r ,输出左边界 l l l
反之输出 − 1 -1 −1
code
cpp
void solve(){
int n,k,q;
cin >> n >> k >> q;
vector<vector<int>>a(n+1,vector<int>(k+1));
vector<vector<int>>b(k+1,vector<int>(n+1));
for(int i=1;i<=n;++i)
for(int j=1;j<=k;++j){
cin >> a[i][j];
a[i][j]|=a[i-1][j];
b[j][i]=a[i][j];
}
while(q--){
int m;cin >> m;
int l=1,r=n;
while(m--){
int k,c;
char o;
cin >> k >> o >> c;
if(o=='<'){
int x=lower_bound(b[k].begin()+1,b[k].end(),c)-b[k].begin();
x--;
r=min(r,x);
}
else{
int x=upper_bound(b[k].begin()+1,b[k].end(),c)-b[k].begin();
l=max(l,x);
}
}
if(l<=r) cout << l << endl;
else cout << -1 << endl;
}
return ;
}