Acwing 第 163 场周赛
A
将数据存入数组,根据下标取最小值
B
根据题意,相邻的两个都是朋友,给出朋友关系,构造满足所有关系的排列
假如此时 2 3 1 4 5 满足朋友关系,那么5之后的第一个数字一定是4的朋友,以此递推,就可以得到排列
所以现在的问题在于,如何得到这个最初始的排列?
由于数据较小,我们以1为其他4个数字的朋友,全排列所有的可能,一个一个去检验即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n;
vector<int >q[maxn];
int nt[5],ans[maxn];
bool book[5],used[maxn];
int get(int x,int a,int b,int c){
for(int v:q[x]){
if(v!=a && v!=b && v!=c) return v;
}
return -1;
}
bool check(){
ans[2]=1;
int d[5]={0,1,3,4};
for(int i=0;i<4;++i)
ans[d[i]]=q[1][nt[i]];//排列输入答案
for(int i=5;i<n+5;++i){
ans[i]=get(ans[i-2],ans[i-4],ans[i-3],ans[i-1]);//递推后面
if(ans[i]==-1) return 0;//出现不可能的构造
}
for(int i=0;i<5;++i)
if(ans[i]!=ans[n+i]) return false;//后5个应该与前5个重叠
memset(used,0,sizeof used);
for(int i=0;i<n;++i){//判重,出现重复的即有错
int t=ans[i];
if(used[t]) return 0;
used[t]=1;
}
for(int i=0;i<n;++i) printf("%d ",ans[i]);
return 1;
}
bool dfs(int u){//全排列
if(u==4) return check();
for(int i=0;i<4;++i)
if(!book[i]){
nt[u]=i;
book[i]=1;
if(dfs(u+1)) return true;
book[i]=0;
}
return 0;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n*2;++i){
int u,v;
scanf("%d %d",&u,&v);
q[u].push_back(v);
q[v].push_back(u);
}
if(!dfs(0)) puts("-1");
return 0;
}
C
经典模型
并查集染色
对于一个区间[l,r]的奶农都被其中的x打败,所以用ans记录他们被谁打败
而被打败的奶牛,用并查集f[]指向后一头牛,由于路径压缩,那么区间内的每头牛都会指向r+1,这样下次涉及该区间操作时,就会跳过该区间
该题中第x头牛会被保留,所以删除的区间是[l,x-1],[x+1,r]
#include<bits/stdc++.h>
using namespace std;
const int maxn= 300010;
int n,m;
int f[maxn], ans[maxn];
int find(int x)
{
if(f[x] != x) return f[x] = find(f[x]);
return f[x];
}
int main()
{
scanf("%d%d", &n, &m);
for (int i=1; i<=n+1; i++) f[i]=i;
while (m--)
{
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
for(int i=find(l);i<x;i=find(i)){
if (i<x){
f[i]=i+1;
ans[i]=x;
}
}
for(int i=find(x+1);i<=r;i=find(i)){
if (i<=r){
f[i]=i+1;
ans[i]=x;
}
}
}
for (int i=1;i<=n;i++) printf("%d ", ans[i]);
return 0;
}
类似题疯狂的馒头
- 温馨提示 cin,cout超时
#include<bits/stdc++.h>
using namespace std;
int n,m,p,q;
int l,r;
const int maxn=2e6+10;
int f[maxn];
int ans[maxn];
int cnt=0;
int find(int x){
if(x!=f[x]) return f[x]=find(f[x]);
return x;
}
int main(){
scanf("%d %d %d %d",&n,&m,&p,&q);
for(int i=1;i<=n+1;++i) f[i]=i;
while(m){
int x = (m * p + q) % n + 1;
int y = (m * q + p) % n + 1;
l=min(x,y);
r=max(x,y);
for(int i=find(l);i<=r;i=find(i)){
ans[i]=m;
f[i]=find(i+1);
}
m--;
}
for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
return 0;
}
本文作者:归游
本文链接:https://www.cnblogs.com/guiyou/p/18697105
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步