比赛连接
Solved: 6/10
A. Kevin and Combination Lock
题意:给一个整数,每次你可以将它减 33 或擦掉一个 33,问能否变成 0。
注意到擦掉 33 不会改变原数模 3 和 11 的余数,因此只需判断原数能否被 33 整除。
#include<bits/stdc++.h>
using namespace std;void solve(){int n;cin>>n;cout<<(n%33?"NO":"YES")<<'\n';
}
int main(){int T;cin>>T;while(T--)solve();
}
B. Kevin and Permutation
题意:构造一个排列 \(p\),使得 \(\sum_{i=1}^{n-k+1}\min_{j=1}^{j+k-1}p_j\) 最小。
每隔 \(k\) 个位置放尽量小的数即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;void solve(){int n,k;cin>>n>>k;vector<int> a(n+1);int j=1;for(int i=k;i<=n;i+=k)a[i]=j,++j;for(int i=1;i<=n;++i)if(!a[i])a[i]=j,++j;for(int i=1;i<=n;++i)cout<<a[i]<<' ';cout<<'\n';
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}
C. Kevin and Binary Strings
题意:给一个 01 串,找出两个子串使得它们的异或和最大。\(|s|\leq 5000\)
因为位数越多越大,所以其中一个子串必为整个串。而另一个串需要高位尽可能是 1。原串的前几个 1 显然可以保留,找到从高位开始第一个 0 的位置,从这一位开始的长度就是第二个串的长度。因为 \(n^2\) 可过,所以直接枚举第二个串的起始位置即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;void solve(){string a;cin>>a;int n=a.length(),pos=-1;for(int i=0;i<n;++i)a[i]-='0';for(int i=0;i<n;++i)if(!a[i]){pos=i;break;}if(pos==-1){cout<<1<<' '<<n<<' '<<1<<' '<<1<<'\n';return;}string mx="";int ans=0;for(int j=0;j<pos;++j){string s=a;for(int k=0;k<n-pos;++k)s[pos+k]^=a[j+k];if(s>mx)mx=s,ans=j;}cout<<1<<' '<<n<<' '<<ans+1<<' '<<ans+n-pos<<'\n';
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}
D. Kevin and Competition Memories
题意:\(n\) 个人,第 \(i\) 个人水平为 \(a_i\),\(m\) 道题,第 \(j\) 道题难度为 \(b_j\)。每个人能做出且仅能做出 \(b_j\leq a_i\) 的题。
每场比赛 \(k\) 道题,举办 \(\lfloor mk\rfloor\) 场比赛,每道题只能供一场比赛。\(n,m\leq 3\times 10^5\)
对每个 \(k\),求所有比赛第 \(1\) 个人排名之和的最小值。
考虑每个人对答案的贡献。设满足 \(a_1<b_j\leq a_i\) 的 \(j\) 共有 \(t_i\) 个,则
\(t_i\) 可以排序后双指针求,处理贡献时可用整除分块+差分数组优化为 \(O(\sqrt m)\)。总复杂度 \(O(n\sqrt m)\)。
好像有点卡常(赛时提交 1900+ms)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()void solve(){int n,m;cin>>n>>m;vector<int> a(n),b(m);for(int& x:a)cin>>x;for(int& x:b)cin>>x;int a0=a[0];sort(all(a)),sort(all(b));int cnt=0,p=n,q=m;for(int i=0;i<n;++i)if(a[i]>a0){p=i;break;}for(int i=0;i<m;++i)if(b[i]>a0){q=i;break;}vector<ll> s(m+2);for(int i=p,j=q;i<n;++i){while(j<m&&b[j]<=a[i])++j;int t=m-(j-q);for(int l=1,r;l<=t;l=r+1){r=t/(t/l);s[l]-=t/l,s[r+1]+=t/l;}}for(int i=1;i<=m;++i)s[i]+=s[i-1];for(int i=1;i<=m;++i)s[i]+=1ll*(n-p+1)*(m/i),cout<<s[i]<<' ';cout<<'\n';
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}
E. Kevin and Bipartite Graph
题意:完全二分图 \(K(2n,m)\),给每条边染色为 \(n\) 种颜色,给出染色方案使得不存在同色环。
纯试出来的构造,不知道有没有更简洁的方法。
\(2n\leq m\) 无解,直接输出 NO。
以 \(n=4\) 为例:
1 1 2 3 4 2 3 4
2 2 3 4 1 3 4 1
3 3 4 1 2 4 1 2
4 4 1 2 3 1 2 3
1 2 3 4 1 2 3 4
2 3 4 1 2 3 4 1
3 4 1 2 3 4 1 2
4 1 2 3 4 1 2 3
取前 \(m\) 行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()void solve(){int n,m;cin>>n>>m;if(n*2<=m){cout<<"NO\n";return;}vector<vector<int>> a(2*n);for(int i=0;i<2*n;++i)a[i].resize(2*n);for(int i=0;i<n;++i){a[i][0]=a[i][1]=i;for(int j=0;j<n;++j)a[n+i][j]=a[n+i][n+j]=(i+j)%n;for(int j=1;j<n;++j)a[i][j+1]=a[i][j+n]=(i+j)%n;}cout<<"YES\n";for(int i=0;i<n*2;++i,cout<<'\n')for(int j=0;j<m;++j)cout<<a[i][j]+1<<' ';
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}
F. Kevin and Math Class
题意:给两个序列 \(a\) 和 \(b\)。每次操作可以选择一个区间 \([l,r]\),令 \(x=\min_{j=l}^r b_j\),然后对每个 \(l\leq i\leq r\) 令 \(a_i\leftarrow \lceil\frac{a_i}x\rceil\)。问最少几次操作可使序列 \(a\) 全为 \(1\)。\(n\leq 2\times 10^5, a_i\leq 10^{18}\)。
容易发现
- 总操作数不超过 \(\log w\leq 60\)。
- 操作顺序一定是从小区间到大区间,除的数从大到小。
对 \(b\) 序列建立笛卡尔树,设 \(f(u,k)\) 表示以 \(u\) 为顶点的子树共操作 \(k\) 次最大值的最小值。则有转移
分两步转移,总复杂度 \(O(n\log^2 w)\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()const int N=2e5+5;
int n;
ll a[N],b[N];
int st[20][N];
ll mx[20][N];
int mini(int i,int j){return b[i]<=b[j]?i:j;
}
int qmni(int l,int r){int o=__lg(r-l+1);return mini(st[o][l],st[o][r-(1<<o)+1]);
}
ll qmx(int l,int r){int o=__lg(r-l+1);return max(mx[o][l],mx[o][r-(1<<o)+1]);
}
ll f[N][60];
int rt,lc[N],rc[N];
int bld(int l,int r){int mid=qmni(l,r);lc[mid]=mid>l?bld(l,mid-1):0;rc[mid]=mid<r?bld(mid+1,r):0;return mid;
}
void dfs(int u){if(lc[u])dfs(lc[u]);if(rc[u])dfs(rc[u]);memset(f[u],0x3f,sizeof(ll)*60);for(int i=0;i<60;++i)for(int j=0;i+j<60;++j)f[u][i+j]=min(f[u][i+j],max(a[u],max(f[lc[u]][i],f[rc[u]][j])));ll g[60];memset(g,0x3f,sizeof(ll)*60);for(int i=0;i<60;++i){ll t=f[u][i];for(int j=0;i+j<60;++j)g[i+j]=min(g[i+j],t),t=(t+b[u]-1)/b[u];}memcpy(f[u],g,sizeof(ll)*60);
}
void solve(){cin>>n;for(int i=1;i<=n;++i)cin>>a[i];for(int i=1;i<=n;++i)cin>>b[i],st[0][i]=i;for(int i=1;1<<i<=n;++i)for(int j=1;j+(1<<i)-1<=n;++j)st[i][j]=mini(st[i-1][j],st[i-1][j+(1<<i-1)]);rt=bld(1,n);dfs(rt);for(int i=0;i<60;++i)if(f[rt][i]==1){cout<<i<<'\n';return;}
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}