链接:https://ac.nowcoder.com/acm/contest/6383/A
来源:牛客网
找卧底
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
牛牛今天和大家玩了一个新游戏,除了牛牛以外还有n个人参加游戏,现在这n个人中的每个人从[1,n]中选择一个数字,保证选出的数字均不重复。牛牛作为第n+1个人,充当卧底的角色,要求卧底从1到n中选择一个数字,现在将n+1个数字重新打乱顺序,请找出卧底选择的数字是多少。
示例1
输入
复制
4,[1,2,1,4,3]
输出
复制
1
备注:
其中1<=n<=100000。
要求时间复杂度为O(n),额外空间复杂度为O(1)
class Solution {
public:
/**
*
* @param n int整型
* @param a int整型vector
* @return int整型
*/
int search(int n, vector<int>& a) {
map<int,int>mp;
for(int i=0;i<a.size();i++){
if(mp[a[i]])return a[i];
mp[a[i]]++;
}
}
};
链接:https://ac.nowcoder.com/acm/contest/6383/B
来源:牛客网
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
题意
在一颗有 nn 个结点且以 11 为根节点树上,起初每个结点的初始权值为 00 。
现在有 qq 次操作,每次操作选择将以 r_ir
i
为根节点的子树上的所有结点权值增加 x_ix
i
。
求 qq 次操作后从 11 到 nn 每个结点的权值。
输入
第一个参数为 nn,1\leq n \leq 100,0001≤n≤100,000
第二个参数为边 (u_i, v_i)(u
i
,v
i
) 的集合,其中 (u_i, v_i)(u
i
,v
i
) 表示结点 u_iu
i
与结点 v_iv
i
之间有一条边,1\leq u_i, v_i \leq n1≤u
i
,v
i
≤n
第三个参数为 qq,1 \leq q \leq 100,0001≤q≤100,000
第四个参数为 qq 次询问的 (r_i, v_i)(r
i
,v
i
) 的集合,1\leq r_i \leq n, 0 \leq \lvert v_i \rvert \leq 1000,0001≤r
i
≤n,0≤∣v
i
∣≤1000,000
返回
从 11 到 nn 每个结点的权值。
示例1
输入
复制
5,[(2,5),(5,3),(5,4),(5,1)],2,[(1, 3), (2, -1)]
输出
复制
[3,2,3,3,3]
说明
第一次操作,将以 1 为根节点的子树上的所有结点权值增加 3,此时结点的权值分别为 [3, 3, 3, 3, 3] ;
第二次操作,将以 2 为根节点的子树上的所有结点权值增加 -1,此时结点的权值分别为 [3, 2, 3, 3, 3] ;
/**
* struct Point {
* int x;
* int y;
* };
*/
const int maxn=1e5+5;
int w[maxn],v[maxn];
vector<int>adj[maxn];
vector<long>ans;
class Solution {
public:
/**
* 从 1 到 n 每个结点的权值。
* @param n int整型
* @param Edge Point类vector (u, v) 集合
* @param q int整型
* @param Query Point类vector Point.x 为题中 r, Point.y为题中 v
* @return long长整型vector
*/
void build(int fa,int u){
w[u]=v[u]+w[fa];
for(auto i:adj[u]){
if(i==fa)continue;
build(u,i);
}
}
vector<long> solve(int n, vector<Point>& a, int q, vector<Point>& Query) {
// write code here
for(int i=0;i<n-1;i++){
int u=a[i].x;
int v=a[i].y;
adj[u].push_back(v);
adj[v].push_back(u);
}
for(int i=0;i<q;i++){
int x=Query[i].x;
int y=Query[i].y;
v[x]+=y;
}
build(0,1);
for(int i=1;i<=n;i++){
ans.push_back(w[i]);
}
return ans;
}
};
链接:https://ac.nowcoder.com/acm/contest/6383/C
来源:牛客网
题目描述
题意
牛牛有一个长为 nn 的排列 pp ,与 mm 对 (x_i, y_i)(x
i
,y
i
) 。
每对 (x_i, y_i)(x
i
,y
i
) 表示可以将 p_{x_i}p
x
i
的值与 p_{y_i}p
y
i
的值互换。
mm 对 (x_i, y_i)(x
i
,y
i
) 的使用顺序与次数不限。
牛牛想知道,任意次操作之后他能得到的字典序最小的排列是什么
字典序定义:对于数字1、2、3…n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是 54321。(来自百度百科)
输入
第一个参数为 nn,1\leq n \leq 100,0001≤n≤100,000
第二个参数为 mm,1\leq m \leq 100,0001≤m≤100,000
第三个参数为初始排列 pp,1\leq p_i\leq n1≤p
i
≤n
第四个参数为 mm 对 (x_i, y_i)(x
i
,y
i
), 1\leq x_i, y_i\leq n, x_i \neq y_i1≤x
i
,y
i
≤n,x
i
=y
i
返回
字典序最小的排列
示例1
输入
复制
5,3,[5,2,3,4,1],[(2,4),(1,4),(3,4)]
输出
复制
[2,3,4,5,1]
说明
- 交换 (3, 4), 交换后的序列为: 5, 2, 4, 3, 1
- 交换 (2, 4), 交换后的序列为: 5, 3, 4, 2, 1
- 交换 (1, 4), 交换后的序列为: 2, 3, 4, 5, 1
/**
* struct Point {
* int x;
* int y;
* };
*/
int f[100010], a[100010];
priority_queue<int ,vector<int > , greater<> >q[100005];
class Solution {
public:
/**
* 返回牛牛所能得到的字典序最小的排列
* @param n int整型
* @param m int整型
* @param perm int整型vector
* @param Pair Point类vector
* @return int整型vector
*/
int find(int x){
if(x==f[x]){
return x;
}
return f[x]=find(f[x]);
}
void Union(int x, int y) {
f[find(x)] = find(y);
}
vector<int> solve(int n, int m, vector<int>& perm, vector<Point>& Pair) {
for (int i = 1; i <= n; i++)f[i]=i;
for (auto i : Pair) Union(i.x, i.y);
for (int i = 1; i <= n; i++) q[find(i)].push(perm[i-1]);
vector<int> ans(n);
for (int i = 1; i <= n; i++){
ans[i-1]=q[find(i)].top();
q[find(i)].pop();
}
return ans;
}
};