文章目录
A. Casimir’s String Solitaire
题意:
给你一个只含
A
,
B
,
C
A,B,C
A,B,C字符串
s
s
s, 每次可以删除一个
A
A
A和一个
B
B
B,或者删除一个
A
A
A和一个
C
C
C,问
是否能把
s
s
s删为空串
思路:
统计
A
,
B
,
C
A,B,C
A,B,C的数量即可,
c
n
t
A
+
c
n
t
C
=
c
n
t
B
cnt_A+cnt_C=cnt_B
cntA+cntC=cntB即为
Y
E
S
YES
YES
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define pb emplace_back
#define mp make_pair
#define endl '\n'
#define fi first
#define se second
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=1,M=2*N;
void solve(){
string s;
cin>>s;
int a=0,b=0,cc=0;
if(SZ(s)&1){
cout<<"NO\n";
return;
}
for(auto c:s)
if(c=='A') a++;
else if(c=='B') b++;
else if(c=='C') cc++;
if(b==a+cc) cout<<"YES\n";
else cout<<"NO\n";
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
B. Shifting Sort
题意:给你一个长度为 n n n的数组 a a a,每次可以选择一个区间 a l ∼ a r a_l \sim a_r al∼ar,并且把这段区间 a l ∼ a l + d − 1 a_l\sim a_{l+d-1} al∼al+d−1,移到数组的最右端, a l ∼ a r → a l + d ∼ a r , a l ∼ a l + d + 1 a_l\sim a_r \to a_{l+d} \sim a_r,a_l\sim a_{l+d+1} al∼ar→al+d∼ar,al∼al+d+1,问你是否可以通过少于 n n n次的操作,使得数组有序
思路:
对
a
a
a元素做一个
1
∼
n
1\sim n
1∼n的映射,每一次找到最小值的下表,把最小值的下标之前的区间
r
o
t
a
t
e
rotate
rotate到数组右端,
r
o
t
a
t
e
(
l
,
r
+
1
,
n
+
1
)
rotate(l,r+1,n+1)
rotate(l,r+1,n+1),表示将一个长度为
n
n
n的数组
l
∼
r
l\sim r
l∼r 放在数组右端
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(x) cout<<#x<<"="<<x<<endl;
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define endl '\n'
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100,M=2*N;
int n;
int a[N],pos[N];
vector<PII> save,ans;
void solve(){
save.clear();
ans.clear();
cin>>n;
rep(i,1,n){
int x;cin>>x;
save.push_back({x,i});
}
sort(ALL(save));
rep(i,0,SZ(save)-1){
auto it=save[i];
a[it.second]=i+1;
}
rep(i,1,n) pos[a[i]]=i;
rep(i,1,n){
if(i==a[i]) continue;
ans.push_back({i,pos[i]-i});
rotate(a+i,a+pos[i],a+1+n);
//rep(j,1,n) cout<<a[j]<<' ';
//cout<<endl;
rep(j,i+1,n) pos[a[j]]=j;
}
cout<<SZ(ans)<<endl;
for(auto it:ans){
cout<<it.first<<' '<<n<<' '<<it.second<<endl;
}
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
C. Ticks
题意:
给你一个只含
∗
*
∗和
.
.
.的
n
∗
m
n*m
n∗m的矩阵,检查它是否能有若干个长度至少为
k
k
k的对勾画成
思路:设定一个全为 . . .的数组 a n s ans ans,遍历每一个位置,分别像左上和右上延伸,如果延申的长度大于等于 k k k,则把 a n s ans ans的这些位置都画成 ∗ * ∗,最后比对 a n s ans ans是否和原矩阵相同
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(x) cout<<#x<<"="<<x<<endl;
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define endl '\n'
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=50,M=2*N;
int n,m,k;
char g[N][N],ans[N][N];
void pr(int x,int y){
int cnt=0;
while(x-cnt>=1&&y-cnt>=1&&y+cnt<=m&&g[x-cnt][y-cnt]=='*'&&g[x-cnt][y+cnt]=='*') cnt++;
if(cnt-1>=k){
rep(i,0,cnt-1){
ans[x-i][y-i]='*';
ans[x-i][y+i]='*';
}
}
}
void solve(){
cin>>n>>m>>k;
rep(i,1,n) rep(j,1,m){
cin>>g[i][j];
ans[i][j]='.';
}
rep(i,1,n) rep(j,1,m){
if(g[i][j]=='*') pr(i,j);
}
rep(i,1,n){
rep(j,1,m)
if(ans[i][j]!=g[i][j]){
cout<<"NO\n";
return;
}
}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
D. Productive Meeting
题意:
有
n
n
n个数,每次任意取出两个数都减一,如果数为
0
0
0就不能选择了,问如何取数使得减的次数最多
思路:
贪心取最大和次大的两个数各减一,用一个堆来维护
AC代码:
#include <bits/stdc++.h>
#include <ostream>
#include <queue>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(x) cout<<#x<<"="<<x<<endl;
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define endl '\n'
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10,M=2*N;
int n;
priority_queue<PII> heap;
vector<PII> ans;
void solve(){
while(SZ(heap)) heap.pop();
ans.clear();
cin>>n;
rep(i,1,n){
int x;
cin>>x;
heap.push({x,i});
}
while(SZ(heap)>=2){
auto t1=heap.top();
heap.pop();
auto t2=heap.top();
heap.pop();
if(t1.first>=1&&t2.first>=1) ans.push_back({t1.second,t2.second});
if(t1.first>=1) heap.push({t1.first-1,t1.second});
if(t2.first>=1) heap.push({t2.first-1,t2.second});
}
cout<<SZ(ans)<<endl;
for(auto t:ans) cout<<t.first<<' '<<t.second<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
E1. Permutation Minimization by Deque
题意:
给你一个长度为
n
n
n的数组,问从头开始插入一个
d
e
q
u
e
deque
deque的最小字典序方案
思路:
贪心每次如果大于队头,则放在队尾,否则放在队首
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define pb emplace_back
#define mp make_pair
#define endl '\n'
#define fi first
#define se second
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10,M=2*N;
int n;
int a[N];
void solve(){
cin>>n;
rep(i,1,n) cin>>a[i];
deque<int> D;
D.push_back(a[1]);
rep(i,2,n){
if(a[i]>D.front()) D.push_back(a[i]);
else D.push_front(a[i]);
}
while(SZ(D)){
cout<<D.front()<<' ';
D.pop_front();
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
E2. Array Optimization by Deque
题意:
给你一个长度为
n
n
n的数组,问从头开始插入一个
d
e
q
u
e
deque
deque的得到最少逆序对
思路:
树状数组+离散化
每次插入一个数时,查询数组中
1
∼
g
e
t
i
d
(
x
)
1\sim getid(x)
1∼getid(x)(放队首的逆序对数量)和
g
e
t
i
d
(
x
+
1
)
∼
n
getid(x+1)\sim n
getid(x+1)∼n(放队尾的逆序对数量)的个数,答案加上两者的最小值,并且把
g
e
t
i
d
(
x
)
getid(x)
getid(x)数量
+
1
+1
+1
AC代码:
#include <bits/stdc++.h>
#include <algorithm>
#include <limits>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(x) cout<<#x<<"="<<x<<endl;
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define endl '\n'
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10,M=2*N;
int n;
int a[N];
int tr[N];
inline int lowbit(int x) {return x&-x;}
void add(int x,int v)
{
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=v;
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
VI num;
int getid(int x){
return lower_bound(ALL(num),x)-num.begin()+1;
}
void solve(){
num.clear();
rep(i,1,n) tr[i]=0;
cin>>n;
rep(i,1,n){
cin>>a[i];
num.push_back(a[i]);
}
sort(ALL(num));
num.erase(unique(ALL(num)),num.end());
int ans=0;
rep(i,1,n){
int t=getid(a[i]);
int x=query(t-1),y=query(n)-query(t);
ans+=min(x,y);
add(t,1);
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
F. Array Stabilization (AND version)
题意:
给定一个只含
0
,
1
0,1
0,1的数组
a
0
…
a
n
−
1
a_0 \dots a_{n-1}
a0…an−1,给定一个操作,把数组右端
d
d
d个元素移动到数组的左端,然后
&
\&
&上未操作之前的数组,问把
a
a
a全变为
0
0
0,最少要操作多少布
思路:
图论+bfs
转化成图论问题,要使数组全为
0
0
0,就是
0
0
0的位置经过若干次操作覆盖了全部位置,
d
i
s
t
[
x
]
dist[x]
dist[x]表示
0
0
0的位置到
x
x
x的最短路,bfs每个为
0
0
0的位置,每步从
p
o
s
→
(
p
o
s
+
n
−
d
)
%
n
pos\to (pos+n-d)\%n
pos→(pos+n−d)%n,答案为
d
i
s
t
[
0
∼
n
−
1
]
dist[0 \sim n-1]
dist[0∼n−1]的最大值,即可满足全部位置
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(x) cout<<#x<<"="<<x<<endl;
#define ll long long
#define int ll
#define mst(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define endl '\n'
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
mt19937 rnd(time(0));
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=1e6+10,M=2*N;
int n,d;
int dist[N];
queue<int> Q;
void solve(){
while(SZ(Q)) Q.pop();
cin>>n>>d;
rep(i,0,n-1) dist[i]=inf;
rep(i,0,n-1){
int x;cin>>x;
if(!x){
dist[i]=0;
Q.push(i);
}
}
while(SZ(Q)){
int t=Q.front();
Q.pop();
if(dist[t]+1<dist[(t+n-d)%n]){
dist[(t+n-d)%n]=dist[t]+1;
Q.push((t+n-d)%n);
}
}
int ans=0;
rep(i,0,n-1) ans=max(ans,dist[i]);
if(ans==inf) cout<<"-1\n";
else cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}