Starters 109 Division 2 (Rated)
比赛录屏
\(Best of N Sets\)
https://www.codechef.com/viewsolution/1031196498
\(Minimum XOR\)
https://www.codechef.com/viewsolution/1031202227
\(Alter Ego\)
https://www.codechef.com/viewsolution/1031240608
\(Chroma Swap\)
题意:给定长度为 \(n\) 的两个数组,再给每个数字一个颜色。可以交换任意次 \(A\) 数组和 \(B\) 数组中相同颜色的数字,能否使得 \(A\) 数组不下降。
解法:其实这道题很显然,两个数组中的相同颜色属于同一个 \(set\) ,每次贪心地选择当前颜色的 \(set\) 能选的最小的。就这样本人wa到了比赛结束,为什么呢?因为如果 \(A\) 数组中的某个颜色在 \(B\) 数组中没有出现过,那么 \(A\) 数组的相同颜色也是不能交换的。
vector<int>col[N];
int a[N],b[N],p[N],idx[N],inb[N];
void solve(){
int n=read();
for(int i=0;i<=2*n;i++){
col[i].clear();
idx[i]=0;
inb[i]=0;
}
for(int i=1;i<=n;i++){
a[i]=read();
}
for(int i=1;i<=n;i++){
p[i]=read();
col[p[i]].push_back(a[i]);
}
for(int i=1;i<=n;i++){
b[i]=read();
}
for(int i=1;i<=n;i++){
int x=read();
col[x].push_back(b[i]);
inb[x]=1;
}
for(int i=0;i<=2*n;i++){
sort(col[i].begin(),col[i].end());
}
int lst=-1;
for(int i=1;i<=n;i++){
int now=p[i];
if(!inb[now]){
if(a[i]<lst){
cout<<"No\n";
return ;
}else{
lst=a[i];
continue;
}
}
while(idx[now]<col[now].size()&&col[now][idx[now]]<lst){
idx[now]++;
}
if(idx[now]>=col[now].size()){
cout<<"No\n";
return ;
}else{
lst=col[now][idx[now]];
idx[now]++;
}
}
cout<<"Yes\n";
//puts(ans>0?"YES":"NO");
//puts(ans>0?"Yes":"No");
}
\(Rigged Game\)
题意:给定一棵 \(n\) 个节点的树,规定选择一个节点 \(x,1 \le x\le n\) ,所有到 \(x\) 的最短路径小于 \(y,0 \le y\le n-1\) 的节点权值和为 \(k\) 。给定一些权值,你可以任意分配这些权值为点权。在对整张图,任意选择 \(x,y\) 时,\(k\) 的最小期望是多少。
场上这题题意读错了,读成了任意选择两个点, \(k\) 为简单路径上的和(扔进Pool)。
解法:这里有两件事要做:计算出所有 \(x,y\) 的权值和与找出最佳分配。对于第二件事,显然我们要把遍历次数最多的点赋更大的权值。而处理第一个问题,怎么看都是换根 \(dp\) 。\(dfs1\) 时需要得到一个点被遍历的次数,\(dfs2\) 时换根得到整棵树每个节点的被遍历次数,而事实上题解采取的是维护不会被遍历的次数。
//赛时这道题好像一开始是D 然后变成E 结束再看变成了F
vector<int>G[N];
int disum[N],subsz[N];
void dfs1(int u ,int fa){
subsz[u]=1;
for(auto v:G[u]){
if(v==fa) continue;
dfs1(v,u);
disum[u]+=disum[v]+subsz[v];
subsz[u]+=subsz[v];
}
}
void dfs2(int u,int fa,int add,int n){
for(auto v:G[u]){
if(v==fa) continue;
dfs2(v,u,add+disum[u]-(disum[v]+subsz[v])+n-subsz[v],n);
}
disum[u]+=add;
}
int qmi(int m, int k, int p){
int res = 1 % p, t = m;
while (k){
if (k&1) res = res * t % p;
t = t * t % p;
k >>= 1;
}
return res;
}
void solve(){
int n=read(),ans=0;
for(int i=1;i<=n;i++){
subsz[i]=0;
disum[i]=0;
G[i].clear();
}
vector<int>w(n+1);
for(int i=1;i<=n;i++){
w[i]=read();
}
for(int i=1;i<n;i++){
int x=read(),y=read();
G[x].push_back(y);
G[y].push_back(x);
}
dfs1(1,-1);
dfs2(1,-1,0,n);
sort(disum+1,disum+1+n);
sort(w.begin()+1,w.end());
for(int i=1;i<=n;i++){
ans+=(n*n-disum[i])%mod*w[i]%mod;
ans%=mod;
}
ans=ans*qmi(n,mod-2,mod)%mod*qmi(n,mod-2,mod)%mod;
cout<<ans<<'\n';
//puts(ans>0?"YES":"NO");
//puts(ans>0?"Yes":"No");
}

浙公网安备 33010602011771号