【学习笔记】AGC059

蓝题都不会做

agc059

My Last ABC Problem

首先一次操作显然最多可以让相邻不同元素对 − 2 -2 2

考虑选取 A A A作为特征元素,那么会分成若干段 B C BC BC交错的区间,如果长度为奇数那么可以先全部变成 B / C B/C B/C再翻过来;如果长度为偶数那么可以看成长度为 2 2 2的段。对于两个长度为 2 2 2的段可以合并在一起,最后如果剩的长度为 4 4 4就再操作 2 2 2次即可。

基于上述观察,我们在询问区间的开头和结尾添一个字母(表示整个区间最终变成的结果),设此时序列长度为 L L L,那么 ⌈ L − 1 2 ⌉ \lceil\frac{L-1}{2}\rceil 2L1就是答案。

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back #define inf 0x3f3f3f3f using namespace std; int n,m; int a[100005],p[100005],cnt; string s; int main(){ ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>m>>s; for(int i=0;i<s.size();i++){ int j=i;while(j+1<s.size()&&s[j+1]==s[i])j++; i=j,a[++cnt]=s[i]-'A',p[cnt]=j+1; } for(int i=1;i<=m;i++){ int l,r;cin>>l>>r,l=lower_bound(p+1,p+1+cnt,l)-p,r=lower_bound(p+1,p+1+cnt,r)-p; if(l==r)cout<<0<<"\n"; else { if(a[l]==a[r])cout<<(r-l+1)/2<<"\n"; else cout<<(r-l+2)/2<<"\n"; } } }

Arrange Your Balls

2 hard 4 me

一个简单的思路是,首先把相同颜色的球排在一起,这样答案是颜色数目 k k k

如果一个颜色段很小,那么可以合并到大的颜色块当中,并且只占一个间隙。

基于上述观察,我们可以贪心的取出任意一个颜色块,然后将其他颜色块插入到它的一个间隙中(这个颜色产生的贡献恰为 1 1 1),这样如果最后剩的颜色块数目 ≤ 2 \le 2 2那么答案是 k − 1 k-1 k1

模拟即可。

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back #define inf 0x3f3f3f3f using namespace std; int T,n,r,id[200005],c[200005],nxt[200005],vis[200005],res[200005]; int cnt,cnt2; pair<int,int>s[200005],s2[200005]; int main(){ // freopen("data.in","r",stdin); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>T; while(T--){ cin>>n;for(int i=1;i<=n;i++)c[i]=nxt[i]=vis[i]=0; for(int i=1;i<=n;i++){ int x;cin>>x,c[x]++; }r=cnt=cnt2=0; for(int i=1;i<=n;i++){ if(!c[i])continue; for(int j=1;j<=c[i];j++)id[j]=++r,res[r]=i; for(int j=1;j<c[i];j++)nxt[id[j]]=id[j+1]; if(c[i]>1){ for(int j=1;j<c[i];j++){ s[++cnt]={id[j],id[j+1]}; } while(cnt2&&cnt){ nxt[s[cnt].fi]=s2[cnt2].fi; nxt[s2[cnt2].se]=s[cnt].se; cnt2--,cnt--; } s2[++cnt2]={id[1],id[c[i]]}; } else{ if(cnt){ nxt[s[cnt].fi]=id[1],nxt[id[c[i]]]=s[cnt].se; cnt--; } else { s2[++cnt2]={id[1],id[c[i]]}; } } } for(int i=1;i<cnt2;i++){ nxt[s2[i].se]=s2[i+1].fi; } for(int i=1;i<=n;i++){ vis[nxt[i]]=1; } int rt=0; for(int i=1;i<=n;i++){ if(!vis[i])rt=i; }assert(rt); while(rt){ cout<<res[rt]<<' ',rt=nxt[rt]; }cout<<"\n"; } }

Guessing Permutation for as Long as Possible

数数题令人头疼

可以把过程想象为在一张图上每次加一条有向边 ( u , v ) (u,v) (u,v),如果存在路径 u ′ → v ′ u'\to v' uv并且 ( u ′ , v ′ ) ≠ E (u',v')\ne E (u,v)=E那么就不合法。

然后考虑所有三元导出子图,如果 ( X , Y ) (X,Y) (X,Y), ( Y , Z ) (Y,Z) (Y,Z)的出现时刻比 ( X , Z ) (X,Z) (X,Z)早,并且满足 X > Y > Z X>Y>Z X>Y>Z,那么就可以确定出 X > Z X>Z X>Z,故而不合法。

直接数原排列 p p p复杂度 O ( 2 n ) O(2^n) O(2n)。既然原排列不好数,那么我们考虑每个原排列一定对应唯一一个完全图,其中每条边的颜色表示两个元素之间的大小关系。

那么我们考虑上述条件相当于 ( X , Y ) , ( Y , Z ) (X,Y),(Y,Z) (X,Y),(Y,Z)的颜色必须不同,那么我们构造一个含 n 2 n^2 n2个点的图,如果不存在二分图匹配那么答案是 0 0 0。否则对于一个连通图有两种染色方案,同时对于一个合法的染色方案,它所对应的图一定不存在环,因此存在拓扑排序,也就存在一个合法的 p p p。综上,我们只要数合法的染色方案即可,设连通块数目为 k k k,则总方案数为 2 k 2^k 2k

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back #define inf 0x3f3f3f3f using namespace std; const int mod=1e9+7; int n,m,id[405][405],a[405][405]; int c[405*405]; vector<pair<int,int>>g[405*405]; void add(int x,int y,int z){ g[x].pb({y,z}),g[y].pb({x,z}); } void dfs(int u,int topf){ c[u]=topf; for(auto v:g[u]){ if(c[v.fi]==-1)dfs(v.fi,topf^v.se); else if(c[v.fi]!=(topf^v.se)){ cout<<0; exit(0); } } } int main(){ // freopen("data.in","r",stdin); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ id[i][j]=id[j][i]=++m; } } for(int i=1;i<=m;i++){ int x,y;cin>>x>>y,a[x][y]=a[y][x]=i; } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ for(int k=j+1;k<=n;k++){ if(a[j][i]<a[i][k]&&a[j][k]<a[i][k]){ add(id[j][i],id[j][k],(i<j)^(j>k)); } else if(a[k][i]<a[i][j]&&a[k][j]<a[i][j]){ add(id[k][i],id[k][j],(i<k)^(k>j)); } else if(a[i][j]<a[j][k]&&a[i][k]<a[j][k]){ add(id[i][j],id[i][k],(j<i)^(i>k)); } } } }memset(c,-1,sizeof c);ll res=1; for(int i=1;i<=m;i++){ if(c[i]==-1){ dfs(i,0),res=res*2%mod; } }cout<<res; }

Grid 3-coloring

这个D实在是不可做啊

我们考虑构造一个与 c c c同余的矩阵 a a a,并且满足 a a a矩阵中相邻位置数字只差恰好为 1 1 1

容易发现,至少存在一个合法的 a a a矩阵与 c c c对应(考虑从左上角开始构造,容易验证不会产生矛盾),如果规定矩阵的数字最小的话那么不难猜想 a a a, c c c矩阵形成一一对应关系。

不妨假设 a 1 , 1 = c 1 , 1 a_{1,1}=c_{1,1} a1,1=c1,1,然后将 4 n − 4 4n-4 4n4个变量全部确定出来。如果存在矛盾那么显然无解。

然后我们得到了有解的必要条件:

1.1 1.1 1.1对于任意 2 ≤ i ≤ n − 1 2\le i\le n-1 2in1,满足 ∣ a i , 1 − a i , n ∣ < n |a_{i,1}-a_{i,n}|<n ai,1ai,n<n 并且 ∣ a 1 , i − a n , i ∣ < n |a_{1,i}-a_{n,i}|<n a1,ian,i<n

考虑给出构造或者直接走人 a i , j = max ⁡ ( { a i , 1 − ( j − 1 ) , a i , n − ( n − j ) , a 1 , j − ( i − 1 ) , a n , j − ( n − i ) } ) a_{i,j}=\max(\{a_{i,1}-(j-1),a_{i,n}-(n-j),a_{1,j}-(i-1),a_{n,j}-(n-i)\}) ai,j=max({ai,1(j1),ai,n(nj),a1,j(i1),an,j(ni)})

这个式子怎么来看呢,首先我们证明 ( n − 2 ) × ( n − 2 ) (n-2)\times (n-2) (n2)×(n2)矩阵中相邻位置的差恰好为 1 1 1

证明非常巧妙,考虑手玩样例,我们会发现 { a i , 1 − ( j − 1 ) , a i , n − ( n − j ) , a 1 , j − ( i − 1 ) , a n , j − ( n − i ) } \{a_{i,1}-(j-1),a_{i,n}-(n-j),a_{1,j}-(i-1),a_{n,j}-(n-i)\} {ai,1(j1),ai,n(nj),a1,j(i1),an,j(ni)}的奇偶性相同,那么相邻位置的每一项都相差 1 1 1,这样最大值相差最多是 1 1 1,又因为奇偶性不同,因此恰好相差 1 1 1

然后考虑边界的取值。假设 ∣ a i , 1 − a i , 2 ∣ ≠ 1 |a_{i,1}-a_{i,2}|\ne 1 ai,1ai,2=1(对于其他情况将矩形旋转即可),那么 a i , 2 ≥ a i , 1 + 3 a_{i,2}\ge a_{i,1}+3 ai,2ai,1+3,如果 a i , 2 = a i , n − ( n − 2 ) a_{i,2}=a_{i,n}-(n-2) ai,2=ai,n(n2)那么 a i , n = a i , 1 + 1 a_{i,n}=a_{i,1}+1 ai,n=ai,1+1与条件矛盾;如果 a i , 2 = a 1 , 2 − ( i − 1 ) a_{i,2}=a_{1,2}-(i-1) ai,2=a1,2(i1)那么 a 1 , 2 ≥ a i , 1 + i + 2 a_{1,2}\ge a_{i,1}+i+2 a1,2ai,1+i+2并且 a 1 , 1 ≤ a i , 1 + i − 1 a_{1,1}\le a_{i,1}+i-1 a1,1ai,1+i1,故而 ∣ a 1 , 2 − a 1 , 1 ∣ ≥ 3 |a_{1,2}-a_{1,1}|\ge 3 a1,2a1,13与条件矛盾;如果 a i , 2 = a n , 2 − ( n − i ) a_{i,2}=a_{n,2}-(n-i) ai,2=an,2(ni)那么证明类似。

综上,我们证明了上述构造的合法性。复杂度 O ( n ) O(n) O(n)

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back #define inf 0x3f3f3f3f using namespace std; int T,n,a[1000005]; int b[1005][1005]; string s; int solve(){ cin>>n>>s;a[1]=s[0]-'0'; for(int i=2;i<=4*n-4;i++){ a[i]=s[i-1]-'0';if(a[i]%3==a[i-1]%3)return 0; if((a[i-1]+1)%3==a[i]%3)a[i]=a[i-1]+1; else a[i]=a[i-1]-1; } if(abs(a[1]-a[4*n-4])!=1)return 0; for(int i=2,j=3*(n-1);i<n;i++,j--){ if(abs(a[i]-a[j])>=n)return 0; } for(int i=n+1,j=4*n-4;i<2*n-1;i++,j--){ if(abs(a[i]-a[j])>=n)return 0; }return 1; } void print(){ for(int i=1;i<n;i++)b[1][i]=a[i]; for(int i=1;i<n;i++)b[i][n]=a[i+n-1]; for(int i=1;i<n;i++)b[n][n-i+1]=a[i+2*(n-1)]; for(int i=1;i<n;i++)b[n-i+1][1]=a[i+3*(n-1)]; for(int i=2;i<n;i++){ for(int j=2;j<n;j++){ b[i][j]=max({b[i][1]-(j-1),b[i][n]-(n-j),b[1][j]-(i-1),b[n][j]-(n-i)}); } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cout<<b[i][j]<<' '; }cout<<"\n"; } } int main(){ freopen("data.in","r",stdin); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>T; while(T--){ cout<<(solve()?"YES":"NO")<<"\n"; print(); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530074.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(35)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示