AtCoder Beginner Contest 410 (A - F)
A - G1
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,k;
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
cin>>k;
int ans=0;
for(int i=1;i<=n;i++){
if(k<=a[i]) ans++;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
B - Reverse Proxy
操作一直接翻进去,操作二每次暴力的找到最小的位置即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,q;
cin>>n>>q;
vector<int> a(n+1);
vector<int> ans(q+1);
for(int i=1;i<=q;i++){
int x;
cin>>x;
if(x!=0){
a[x]++;
ans[i]=x;
}
else{
int mn=inf,idx=-1;
for(int j=1;j<=n;j++){
if(a[j]<mn){
mn=a[j];
idx=j;
}
}
a[idx]++;
ans[i]=idx;
}
}
for(int i=1;i<=q;i++){
cout<<ans[i]<<" ";
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
C - Rotatable Array
可以每次 \(O(1)\) 的维护字符串开头的位置,而不需要每次真的对字符串移动
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,q;
cin>>n>>q;
vector<int> a(n);
iota(a.begin(),a.end(),1);
int now=0;
while(q--){
int op,p,x;
cin>>op>>p;
if(op==1){
p--;
cin>>x;
a[(p+now)%n]=x;
}
else if(op==2){
p--;
cout<<a[(p+now)%n]<<endl;
}
else{
now+=p;
now%=n;
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
D - XOR Shortest Walk
注意到 \(n\) 和值域都很小,所以可以直接 DP
设 \(f[i] [j]\) 表示走到点 \(i\) 且当前路径异或和为 \(j\) 的路径是否存在
状态转移可以直接枚举 \(i\) 的所有相邻节点
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,m;
cin>>n>>m;
vector<vector<pii>> g(n+1);
vector<vector<int>> f(n+1,vector<int>(1025));
while(m--){
int a,b,w;
cin>>a>>b>>w;
g[a].push_back({b,w});
}
queue<pii> q;
q.push({1,0});
f[1][0]=1;
while(q.size()){
auto [u,now]=q.front();
q.pop();
for(auto [v,w]:g[u]){
if(!f[v][w^now]){
f[v][w^now]=1;
q.push({v,w^now});
}
}
}
for(int i=0;i<1024;i++){
if(f[n][i]){
cout<<i;
return;
}
}
cout<<-1;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
E - Battles in a Row
设 \(f[i] [j]\) 表示花费 \(i\) 的生命值和 \(j\) 的魔法值最远可以走到哪
假设 \(f[i] [j]~=~k\),则转移时可以尝试花费生命值或魔法值转移到 \(k+1\) 的位置
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,h,m;
cin>>n>>h>>m;
vector<pii> a(n+1);
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
a[i]={x,y};
}
vector<vector<int>> f(h+1,vector<int>(m+1,-inf));
f[0][0]=0;
int ans=0;
for(int i=0;i<=h;i++){
for(int j=0;j<=m;j++){
if(f[i][j]<0 || f[i][j]==n) continue;
int nxt=f[i][j]+1;
auto [nxth,nxtm]=a[nxt];
if(i+nxth<=h){
f[i+nxth][j]=max(nxt,f[i+nxth][j]);
ans=max(ans,f[i+nxth][j]);
}
if(j+nxtm<=m){
f[i][j+nxtm]=max(nxt,f[i][j+nxtm]);
ans=max(ans,f[i][j+nxtm]);
}
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
F - Balanced Rectangles
第一步肯定是转换为 \(0,1\) 矩阵
暴力枚举复杂度显然是 \(O(H*W*H*W)\) 的
可以每次枚举矩形的上下界,固定上下界 \(up,down\) 后,问题就变成了,在这个一维的图形中,有多少 \(l,r\) 满足区间和为 \(0\)
而这一步可以用 \(map\) 或数组记录前缀和出现的次数,从而 \(O(W)\) 的计算 (\(map\) 复杂度过高;又因为会出现负数,所以数组维护需要加一个偏移量)
这样最后的复杂度是 \(O(H*H*W)\),但可能存在 \(H=3e5,~W=1\) 的情况
所以当 \(H>W\) 时,将矩阵旋转 \(90\) 度,交换 \(H,W\) 即可。\(min(H,W)<=\sqrt{H*W}\),所以复杂度是 \(O(H*W*\sqrt{H*W})\)
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
const int N=3e5;
int cnt[1000000];
void solve(){
int n,m;
cin>>n>>m;
//n*n*m
vector<vector<int>> g(n+1,vector<int>(m+1));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char ch;
cin>>ch;
g[i][j]=(ch=='#'?1:-1);
}
}
if(n>m){
vector<vector<int>> t(m+1,vector<int>(n+1));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
t[m-j+1][i]=g[i][j];
}
}
g=t;
swap(n,m);
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// cout<<g[i][j]<<" ";
// }
// cout<<endl;
// }
int ans=0;
for(int u=1;u<=n;u++){
vector<int> sum(m+1);
for(int d=u;d<=n;d++){
for(int i=1;i<=m;i++){
sum[i]+=g[d][i];
}
cnt[N]=1;
vector<int> pre(m+1);
for(int i=1;i<=m;i++){
pre[i]=sum[i]+pre[i-1];
ans+=cnt[pre[i]+N];
cnt[pre[i]+N]++;
}
for(int i=1;i<=m;i++){
cnt[pre[i]+N]--;
}
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}