题目链接:https://ac.nowcoder.com/acm/contest/6383
A-找卧底
题意:原本有n个人,现在多了一个卧底,找出排列中个数超过1的数
hint:用vis标记一下已经存在的人,如果已经存在了,那么当前这个人就是卧底
AC代码:
class Solution {
public:
/**
*
* @param n int整型
* @param a int整型vector
* @return int整型
*/
int search(int n, vector<int>& a) {
// write code here
int vis[100005]={0};
for(int i=0;i<=n;i++){
if(vis[a[i]])return a[i];
vis[a[i]]=1;
}
}
};
B-父子情深
题意:n结点的树,以1为根节点,q次操作,将x为根结点的子树上所有的结点权值加k,输出q次操作之后1到n结点的权值
hint:dfs深搜
因为是自上而下的传递,所以可以先将x结点的权值加上k,最后dfs深搜将父结点状态传给子节点 。
AC代码:
扫描二维码关注公众号,回复:
11485832 查看本文章
/**
* struct Point {
* int x;
* int y;
* };
*/
class Solution {
public:
int f[123456];
vector<int>v[123456];
vector<long>val;
void add(int a,int b){
v[a].push_back(b);
v[b].push_back(a);
}
void dfs(int s,int fa){//dfs找爸爸
for(auto i:v[s]){
if(i==fa)continue;
f[i]=s;
dfs(i,s);
}
}
void dfs1(int s,int fa){//自上而下更新
for(auto i:v[s]){
if(i==fa)continue;
val[i-1]+=val[s-1];
dfs1(i,s);
}
}
vector<long> solve(int n, vector<Point>& Edge, int q, vector<Point>& Query) {
// write code here
val.resize(n,0);
for(auto i:Edge){
add(i.x,i.y);
}
f[1]=-1;
dfs(1,-1);
for(auto i:Query){
val[i.x-1]+=i.y;
}
dfs1(1,-1);
return val;
}
};
C-旋转跳跃
题意:给一个初始排列,以及m对(xi,yi)其中xi,yi位置的元素可以交换无数次 ,问最终可以得到的字典序最小的排列
hint:并查集 +sort
可以将同一连通块的下标存放在一个数组里,然后将数组里下标表示的值从小到大排个序,然后再依次放回原排列,那么的得到的排列字典序是最小的
class Solution {
public:
int pre[123456];
int find(int a){
if(a==pre[a])return a;
return pre[a]=find(pre[a]);
}
vector<int>r;
vector<int>v[123456];
vector<int> solve(int n, int m, vector<int>& perm, vector<Point>& Pair) {
// write code here
for(int i=1;i<=n;i++)pre[i]=i;
for(auto i:Pair){
int u=find(i.x),v=find(i.y);
if(u!=v)pre[u]=v;
}
for(int i=1;i<=n;i++){
int t=find(i);
v[t].push_back(i);
if(i==t)r.push_back(i);
}
for(auto i:r){
vector<int>a;
sort(v[i].begin(),v[i].end());
for(auto j:v[i])a.push_back(perm[j-1]);
sort(a.begin(),a.end());
for(int j=0;j<v[i].size();j++){
perm[v[i][j]-1]=a[j];
}
}
return perm;
}
};