There are n workers in a company, each of them has a unique id from 1 to n. Exaclty one of them is a chief, his id is s. Each worker except the chief has exactly one immediate superior.
There was a request to each of the workers to tell how how many superiors (not only immediate). Worker's superiors are his immediate superior, the immediate superior of the his immediate superior, and so on. For example, if there are three workers in the company, from which the first is the chief, the second worker's immediate superior is the first, the third worker's immediate superior is the second, then the third worker has two superiors, one of them is immediate and one not immediate. The chief is a superior to all the workers except himself.
Some of the workers were in a hurry and made a mistake. You are to find the minimum number of workers that could make a mistake.
The first line contains two positive integers n and s (1 ≤ n ≤ 2·105, 1 ≤ s ≤ n) — the number of workers and the id of the chief.
The second line contains n integers a1, a2, ..., an (0 ≤ ai ≤ n - 1), where ai is the number of superiors (not only immediate) the worker with id i reported about.
Print the minimum number of workers that could make a mistake.
3 2
2 0 2
1
5 3
1 0 0 4 1
2
In the first example it is possible that only the first worker made a mistake. Then:
- the immediate superior of the first worker is the second worker,
- the immediate superior of the third worker is the first worker,
- the second worker is the chief.
- 题意:有n个人,其中一个是大boss,他没有上司,剩下每个人都有一个顶头上司,现在让每个人回答自己有几个上司,问至少有几个人说错了?
- 思路:因为每个人都有顶头上司,所以上司的个数必然是连续的,也就是说,如果有一个人有3个上司,那么必然有人有2个上司,有人有1个上司。
- 当然,不是大boss的人不能有0个上司,大boss必然只有0个上司,如果不满足这两点那么ans都要++,并且将前者纳入叫错但还未纠正的人(记为j个)
- 搜索一遍,记录vis[i]表示有i上司的人有几个。再从i=1开始遍历,sum(人数)初始值为1(1为那个大boss),如果vis[i]>0则往后遍历,记录sum(人数)+=vis[i],如果vis[i]==0,那么说明这个位置应该有人但是现在却没人,所以有人说错了,这个时候从之前的j个人里过来一个作为填补,所以j--,sum++,
- 一旦sum等于总人数,那么终止遍历,如果j==0之后,如果vis[i]==0 那么就说明后面有人说错了,所以sum++,ans++。
- 最后ans即为答案
1 #include <cstdio> 2 #include <ctime> 3 #include <cstdlib> 4 #include <iostream> 5 #include <cstring> 6 #include <cmath> 7 #include <queue> 8 #include <algorithm> 9 #define N 200005 10 #define inf 1e18+5 11 typedef long long ll; 12 #define rep(i,n) for(i=1;i<=n;i++) 13 using namespace std; 14 int i,j,k,m,n,t,cc,ans; 15 int a[N],vis[N]; 16 int s; 17 int main() 18 { 19 while(scanf("%d%d",&n,&s)!=EOF){ 20 memset(vis,0,sizeof(vis)); 21 ans=0; 22 j=0; 23 rep(i,n){ 24 scanf("%d",&a[i]); 25 vis[a[i]]++; 26 if(i!=s&&a[i]==0){ 27 ans++; 28 j++; 29 } 30 if(i==s&&a[i]!=0){ 31 vis[a[i]]--; 32 ans++; 33 a[i]=0; 34 vis[0]++; 35 } 36 } 37 i=1; 38 int sum=1; 39 while(sum<n){ 40 if(vis[i]){ 41 if(sum+vis[i]<n) sum+=vis[i]; 42 else break; 43 } 44 else{ 45 if(j){ 46 j--; 47 } 48 else { 49 ans++; 50 } 51 sum++; 52 53 } 54 i++; 55 } 56 // if(a[1]==121&&a[2]==158) for(i=100;i<=200;i++) printf("%d ",a[i]); 57 58 printf("%d ",ans); 59 // printf("%d aaa",a[142]); 60 } 61 62 63 return 0; 64 }
- 最后ans即为答案