Educational Codeforces Round 169 (Rated for Div. 2) 补题记录(A~F)
打的还行
A
容易发现当且仅当 \(n=2\) 且 \(|a_1-a_2|>1\) 时才可能,否则一定不可能。
const int N=1000100;
int a[N];
signed main(){
int T;cin>>T;
while(T--){
int n;cin>>n;
F(i,1,n)cin>>a[i];
sort(a+1,a+n+1);
if(n==2){
if(a[2]-a[1]==1)cout<<"NO\n";
else cout<<"YES\n";
}else{
cout<<"NO\n";
}
}
return 0;
}
B
暴力枚举求出两段区间的公共区间长度,然后如果左边还有一个位置被至少一条线段覆盖那么需要加 \(1\),右边也同理。细节有点多。
const int N=1000100;
int a[N];
int get(int a,int b,int c,int d){
if(b<c||a>d)return 0;
int s=min(b,d)-max(a,c)+1;
return max(0ll,s);
}
signed main(){
int T;cin>>T;
while(T--){
int l,r,L,R;
cin>>l>>r>>L>>R;
int cnt=0;
int p2=min(r,R),p1=max(l,L);
if(get(l,r,L,R)==0){
cout<<"1\n";
continue;
}
if(get(l,r,L,R)==1){
cout<<"2\n";
continue;
}
--r,--R;
F(i,1,100){
if(l<=i&&i<=r&&L<=i&&i<=R)++cnt;
}
if(l!=L)++cnt;
if(r!=R)++cnt;
cout<<cnt<<'\n';
}
return 0;
}
C
很显然从大到小排序则若 \(i\equiv 0(\bmod 2)\) 则这个元素归 Bob,否则归 Alice。显然 Bob 只能让自己的元素的值和在它前面一个位置的元素的值尽量的接近的时候最优。因此直接暴力枚举 Bob 的每一个元素计算其可以最多加多少,贪心计算即可。时间复杂度为 \(O(n\log n)\),使用基数排序可以做到 \(O(n)\)。
const int N=1000100;
int a[N];
signed main(){
int T;cin>>T;
while(T--){
int n,k;cin>>n>>k;
F(i,1,n)cin>>a[i];
sort(a+1,a+n+1,greater<int>());
int cnt=0;
for(int i=2;i<=n;i+=2){
int diff=a[i-1]-a[i];
diff=min(diff,k);
a[i]+=diff;
k-=diff;
}
sort(a+1,a+n+1,greater<int>());
F(i,1,n){
if(i&1)cnt+=a[i];
else cnt-=a[i];
}
cout<<cnt<<'\n';
}
return 0;
}
D
大分讨。发现若 \(i\) 可以直接到达 \(j\) 则答案就是 \(|i-j|\)。否则要么不能到达要么无解,要么在经过恰好一个中转点的情况下就能到达 \(j\)。因此设 \(f_{i,0/1/2/3/4/5}\) 表示 \(i\) 开始往左第一个为 BG
、BR
、BY
、GR
、GY
、RY
的位置,\(g_{i,0/1/2/3/4/5}\) 表示 \(i\) 开始往右第一个为 BG
、BR
、BY
、GR
、GY
、RY
的位置。这个可以一遍扫描预处理。对于每一个 \(S_{x_i}\) 字符串的值,只需要枚举其可以到达且和自己不完全相同的 \(8\) 个不同的最近组合位置即可。时间复杂度为 \(O(n)\)。
using namespace std;
const int N=500100;
int a[N],fa[N];
string s[N];
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
int f[N][6],g[N][6];
signed main(){
int T;cin>>T;
while(T--){
int n,q;cin>>n>>q;
F(i,1,n)cin>>s[i];
F(i,1,n)if(s[i][0]>s[i][1])swap(s[i][0],s[i][1]);
F(i,1,n)fa[i]=i;
F(i,0,n+1)
F(j,0,5)f[i][j]=g[i][j]=-1;
int la[6]={1,1,1,1,1,1};
F(i,1,n){
if(s[i]=="BG"){
F(j,la[0],i)g[j][0]=i;
la[0]=i+1;
}
if(s[i]=="BR"){
F(j,la[1],i)g[j][1]=i;
la[1]=i+1;
}
if(s[i]=="BY"){
F(j,la[2],i)g[j][2]=i;
la[2]=i+1;
}
if(s[i]=="GR"){
F(j,la[3],i)g[j][3]=i;
la[3]=i+1;
}
if(s[i]=="GY"){
F(j,la[4],i)g[j][4]=i;
la[4]=i+1;
}
if(s[i]=="RY"){
F(j,la[5],i)g[j][5]=i;
la[5]=i+1;
}
}
F(i,0,5)la[i]=n;
G(i,n,1){
if(s[i]=="BG"){
G(j,la[0],i)f[j][0]=i;
la[0]=i-1;
}
if(s[i]=="BR"){
G(j,la[1],i)f[j][1]=i;
la[1]=i-1;
}
if(s[i]=="BY"){
G(j,la[2],i)f[j][2]=i;
la[2]=i-1;
}
if(s[i]=="GR"){
G(j,la[3],i)f[j][3]=i;
la[3]=i-1;
}
if(s[i]=="GY"){
G(j,la[4],i)f[j][4]=i;
la[4]=i-1;
}
if(s[i]=="RY"){
G(j,la[5],i)f[j][5]=i;
la[5]=i-1;
}
}
while(q--){
int x,y;cin>>x>>y;
if(x==y)cout<<"0\n";
else{
if(x>y)swap(x,y);
set<char>se={s[x][0],s[x][1],s[y][0],s[y][1]};
if(se.size()!=4)cout<<abs(y-x)<<'\n';
else{
int res=1e18;
if(s[x]=="BG"){
{int p1=f[x][1],p2=g[x][1];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][2],p2=g[x][2];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][3],p2=g[x][3];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][4],p2=g[x][4];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
}
if(s[x]=="BR"){
{int p1=f[x][0],p2=g[x][0];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][2],p2=g[x][2];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][3],p2=g[x][3];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][5],p2=g[x][5];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
}
if(s[x]=="BY"){
{int p1=f[x][0],p2=g[x][0];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][1],p2=g[x][1];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][4],p2=g[x][4];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][5],p2=g[x][5];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
}
if(s[x]=="GR"){
{int p1=f[x][0],p2=g[x][0];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][1],p2=g[x][1];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][4],p2=g[x][4];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][5],p2=g[x][5];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
}
if(s[x]=="GY"){
{int p1=f[x][0],p2=g[x][0];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][2],p2=g[x][2];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][3],p2=g[x][3];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][5],p2=g[x][5];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
}
if(s[x]=="RY"){
{int p1=f[x][1],p2=g[x][1];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][2],p2=g[x][2];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][3],p2=g[x][3];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
{int p1=f[x][4],p2=g[x][4];
if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
}
if(res>=1e17)res=-1;
cout<<res<<'\n';
}
}
}
}
return 0;
}
E
不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。不要读错题。下回你就没有 \(5\) min 切的运气了。
发现每一堆石子之间互相独立,因此考虑分别计算其 SG 函数的值然后异或。首先可以写出暴力 \(O(n)\) 计算 SG 值程序打表,然后可以发现如下的规律:
- \(\text{SG}(x)=0\),\(2\mid x\)。
- \(\text{SG(x)}=1\),\(x=1\)。
- \(\text{SG(x)}=\text{ID}_x\),\(x\in\text{Prime}\)。
- \(\text{SG(x)}=\min\limits_{i=1}^k \text{ID}_{v_i}\),满足 \(k\ge 2\) 有 \(\prod\limits_{i=1}^k v_i=x\) 且 \(v_i\in\text{Prime}\)。
因此可以使用重科技 Pollard-Rho 分解质因数,也可以一遍线性筛素数计算出每一个 \(x\) 的最大质因数然后每一次除以这个数得到其所有的质因子。因此做完了。
const int N=10000010;
int a[N],n,Sg[10000005],FR[N];
int id[10000005];
int prime[N], tot;
bool np[N];
void sieve(int maxn) {
np[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!np[i]) {
prime[++tot] = i;
id[i]=tot;
FR[i]=i;
}
for (int j = 1; j <= tot && i * prime[j] <= maxn; j++) {
np[i * prime[j]] = true;
FR[i*prime[j]]=prime[j];
if (i % prime[j] == 0) {
break;
}
}
}
}
int SG(int x){
if(~Sg[x])return Sg[x];
if(x%2==0)return 0;
if(x==1)return 1;
if(!np[x])return id[x];
int mi=1e9;
while(x>1){
mi=min(mi,id[FR[x]]);
x/=FR[x];
}
return mi;
}
signed main(){
memset(Sg,-1,sizeof Sg);
Sg[0]=0;
sieve(N-9);
int T;cin>>T;
while(T--){
cin>>n;
F(i,1,n)cin>>a[i];
int sg=0;
F(i,1,n)sg^=SG(a[i]);
if(sg)cout<<"Alice\n";
else cout<<"Bob\n";
}
return 0;
}
F
不太会的题。看到 \(n\le 2000\) 和区间问题想到区间 dp。设 \(f_{i,j}\) 表示问 \(i\sim j\) 一段区间中所需要的最小的操作次数。则容易发现 \(2\) 操作完全迷惑人没有任何用途,只需要暴力转移 \(1\) 操作即可。
令 \(s_i=\sum\limits_{j=1}^i a_i\),\(\text{Map}_i\) 表示出现 \(i\) 值的时候对答案造成的最小贡献是多少。
具体转移有:
- (\(1\))\(f_{i,j}=j-i\)
- (\(2\))\(f_{i,j}=j-i+\text{Map}_{s_{i-1}+s_j}\)
然后更新 \(\text{Map}_{s_{i-1}+s_j}\) 的值即可。
时间复杂度为 \(O(n^2)\) 或者 \(O(n^2\log n)\)。
const int N=500100;
int a[N],s[N];
int f[3010][3010];
signed main(){
int T;cin>>T;
while(T--){
int n;cin>>n;
F(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i];
map<int,int>mp;
G(i,n,1)F(j,i-1,n){
if(j!=i-1){
f[i][j]=j-i;
if(mp.count(s[i-1]+s[j]))
f[i][j]=min(f[i][j],mp[s[i-1]+s[j]]+(j-i));
}else f[i][j]=0;
if(!mp.count(s[i-1]+s[j]))
mp[s[i-1]+s[j]]=f[i][j]-j+i-2;
else
mp[s[i-1]+s[j]]=min(mp[s[i-1]+s[j]],f[i][j]-j+i-2);
}
int sum=0;
F(i,1,n)F(j,i-1,n)sum+=f[i][j];
cout<<sum<<'\n';
}
return 0;
}
G
完全不会做。咕咕咕。
本文来自博客园,作者:yhbqwq,转载请注明原文链接:https://www.cnblogs.com/yhbqwq/p/18362235,谢谢QwQ