0%

90801202-AGC006

B

一个数字三角形,最下层的值是 $1\sim 2n-1$ 的排列,其余的值是正下,左下,右下方三个值的中位数,给定 $n,x$ , 求能构造出顶端是 $x$ 的最下层排列

先考虑无解:即 $x=1 或 x=2n-1$ 时无解

其次可以发现,对于两个相邻的相同数字,该数字会一直向上延伸

而 $x$ 就是离对称轴最近且满足条件的数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const int N=2e5+100;
int n,x,p[N],vis[N];

int main(){
scanf("%d%d",&n,&x);
if(x==1 || x==2*n-1) return puts("No"),0;
puts("Yes");
p[n]=x;
p[n-1]=x==2 ? x+1 : x-1,p[n+1]=x==2 ? x-1 : x+1,p[n+2]=x==2 ? x+2 : x-2;
vis[x]=vis[x+1]=vis[x-1]=vis[x==2 ? x+2 : x-2]=1;
for(rei i=1,j=1;i<=2*n-1;++i){
if(p[i]) continue;
while(vis[j]) ++j;
p[i]=j,vis[j]=1;
}
for(rei i=1;i<=2*n-1;++i) printf("%d\n", p[i]);
getchar(),getchar();
return 0;
}

C

数轴上有 $n$ 只兔子,第 $i$ 只位于 $a_i$ ,做 $k$ 次移动,每次由 $m$ 次跳跃,对于第 $j$ 次跳跃,第 $c_j$ 只兔子等概率选取 $c_{j-1}$ 或 $c_{j+1}$ 的兔子并跳到其对称点,求每一只兔子最终位置的期望

对于兔子 $c_j$ ,跳跃后会转移到 $2\times c_{j-1}-c_j$ 或 $2\times c_{j+1}-c_j$

所以有 $f’_{c_j}=\frac{2\times f_{c_{j-1}}-f_{c_j}+2\times f_{c_{j+1}}-f_{c_j}}{2}=f_{c_{j-1}}+f_{c_{j+1}}-f_{c_j}$

而进行 $k\leq 10^{18}$ 轮,时间复杂度显然会爆

$\text{ctp_314}$ 告诉我们,遇到转移问题难以转移就想一想差分,即, $d_i=f_i-f_{i-1}$

差分的转移为:

恰好是交换,那么求出循环节即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const int N=1e5+100;
int n,m,a[N],f[N],s[N],top,vis[N];
ll ans[N],k;
int main(){
scanf("%d",&n);
for(rei i=1;i<=n;++i) scanf("%d",&a[i]);
for(rei i=n;i;--i) a[i]-=a[i-1],f[i]=i;
scanf("%d%lld",&m,&k);
for(rei i=1,p;i<=m;++i) scanf("%d",&p),swap(f[p],f[p+1]);
for(rei i=1;i<=n;++i,top=0)
if(!vis[i]){
for(rei j=i;!vis[j];j=f[j]) vis[j]=1,s[++top]=j;
for(rei j=1;j<=top;++j) ans[ s[j] ]=a[ s[(j+k-1)%top+1] ];
}
for(rei i=1;i<=n;++i) printf("%lld\n",ans[i]+=ans[i-1]);
getchar(),getchar();
return 0;
}

D

数字三角形,生成规则与 $B$ 相同,给定第 $n$ 行的数列,求第 $1$ 行的

不会的二分贪心思维题

二分顶端的数,由于用中位数生成,所以数列中只需要保留与顶端数的大小关系,即将原数列转化为 $01$ 串

由 $B$ 推出的性质推广得:当存在两个相邻的 $0/1$,且不与边界相邻,那么可以一直向上走

即,离对称轴最近且长度至少为 $2$ 的连续段就是顶端答案

最后特判不存在该连续段的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const int N=2e5+100;
int n,ans=2,p[N];

inline bool valid(int mid){
for(rei i=0;i<n-1;++i)
if(max(p[n-i],p[n-i-1])<=mid || max(p[n+i],p[n+i+1])<=mid) return true;
else if(min(p[n-i],p[n-i-1])>mid || min(p[n+i],p[n+i+1])>mid) return false;
return p[1]<=mid;
}

int main(){
scanf("%d",&n); for(rei i=2*n-1;i;--i) scanf("%d",&p[i]);
rei l=2,r=2*n-2;
while(l<=r){
rei mid=l+r>>1;
valid(mid) ? r=mid-1,ans=mid : l=mid+1;
}
printf("%d\n",ans);
getchar(),getchar();
return 0;
}

E

给定 $3\times N$ 的矩阵,点 $(i,j)$ 的数为 $i+3j-3$ 。有操作:选择 $3\times 3$ 的矩阵,并将其旋转 $180^。$ 。给定目标矩阵,询问是否可以转化

首先考虑无解:

  • 将每一列看为一个整体,整体内部的元素组成不变
  • 所有模 $3$ 余 $2$ 的数一定在第二行

再考虑性质:每次以 $(i,2)$ 为中心旋转实际是交换 $i-1,i+1$ 列,并将 $[i-1,i+1]$ 上下颠倒 —— 将上下颠倒看作奇偶性,奇数时要上下颠倒

将每一列当成字母,小写为颠倒前,大写为颠倒后,设 $abcde$ 为原矩形的部分

其次可以推出结论:

  • 可以将隔着一列的两列数同时颠倒

  • 可以同时改变相邻 $4$ 列的奇偶性

$\therefore$ 可以成对改变边的奇偶性,那么只需要考虑最终状态 奇数列 与 偶数列上下颠倒个数 的奇偶性,若都为偶则合法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const int N=1e5+100;
int w[3][N],f[N],h[2],n;

int main(){
scanf("%d",&n);
for(rei i=0;i<3;++i) for(rei j=1;j<=n;++j) scanf("%d",&w[i][j]);
for(rei i=1;i<=n;++i){
rei a=w[0][i],b=w[1][i],c=w[2][i];
if(abs(a-b)>1 || abs(b-c)>1 || b%3!=2 || (b%6 & i&1)) return puts("No"),0;
f[i]=b/3+1,h[i&1]^=a>c;
}
for(rei i=1;i<=n;++i) while(f[i]!=i) h[ i&1^1 ]^=1,swap(f[i],f[ f[i] ]);
h[0]||h[1] ? puts("No") : puts("Yes");
getchar(),getchar();
return 0;
}

F

给定 $n\times n$ 的网格,给定黑点坐标,其余白色,若存在 $(x,y)$ 和 $(y,z)$ 则会出现一个 $(z,x)$ 的黑点,求最终黑点数

若 $(x,y)$ 为黑色,则连 $x\rightarrow y$ 的边,将题目等价于:若有 $x\rightarrow y 且 y\rightarrow z$ ,则有 $z\rightarrow x$

如此连边不会影响连通性,只需考虑一个连通块内的情况并累加即可

由连边方式构成的三元环结构引导我们对图染色

连边方式自然定为:若 $x\rightarrow y$ , 则有 $col(x)+1\equiv col(y) \pmod 3$

对染色情况分类:

  • 所有点只用 $\leq 2$ 中颜色且成功

    即没有出现新边,最终边数 $|E’|$ 等于原边数 $|E|$

  • 所有点用 $3$ 种颜色且成功

    可以证明此时图 $G$ 具有完全三分图的结构

    在此情况下,总边数等于各个部分大小的两两乘积和

  • 染色失败

    设加入边 $(u,v)$ 时失败,即,加入该边前 $u,v$ 已经连通,此时他们所在的连通分量是一个完全三分图

    考虑失败原因

    • $1\rightarrow 0$

      即自环存在于 $0\rightarrow 1\rightarrow 0$

    • $0\rightarrow 0$

      即有 $0\rightarrow 0\rightarrow 1\rightarrow 0$

    对于自环 $s\rightarrow s$ ,可以证明所有与 $s$ 相连的点 $u$ ,都有重边; 而对于 $\forall v,u$ 都有 $v\rightarrow s\rightarrow u \rightarrow v$

    即,图 $G$ 完全图

    该情况下总边数时连通分量大小的平方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const int N=1e5+100;
int head[N],Next[N<<1],ver[N<<1],tot;
int col[N],c[3],n,m,ce;
ll ans;

inline void add(int u,int v){ ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}

bool dfs(int x){
bool result=true; ++c[ col[x] ];
for(rei i=head[x];i;i=Next[i]){
rei y=ver[i];
rei c=(col[x]+2-(i&1))%3; ++ce;
result&=(~col[y] ? col[y]==c : (col[y]=c,dfs(y)));
}
return result;
}

int main(){
scanf("%d%d",&n,&m);
for(rei i=1,u,v;i<=m;++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
memset(col,-1,sizeof col);
for(rei i=1;i<=n;++i)
if(!~col[i]){
c[0]=c[1]=c[2]=ce=col[i]=0;
if(!dfs(i)) ans+=(ll) (c[0]+c[1]+c[2])*(c[0]+c[1]+c[2]);
else if(c[0] && c[1] && c[2]) ans+=(ll) c[0]*c[1]+(ll) (c[0]+c[1])*c[2];
else ans+=ce>>1;
}
printf("%lld\n",ans);
getchar(),getchar();
return 0;
}