【2018百度之星初赛 B】1001并查集 1004二分 1006不等式

1001 degree

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6380

并查集向图中加点,分别记录与初始度数最多的点 直接相连的点数、独立的点数;则间接相连的点数 = n-1-直接相连的点数;

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<set>
 4 #include<map>
 5 using namespace std;
 6 
 7 int T,n,m,k;
 8 int f[200005], a[200005];
 9 
10 int find(int x) {
11     if(f[x]!=x)
12         f[x]=find(f[x]);
13     return f[x];
14 }
15 
16 void Union(int x, int y) {
17     int w = find(x);
18     int s = find(y);
19     f[w] = s;
20 }
21 
22 int main()
23 {
24     cin>>T;
25     while(T--)
26     {
27         cin>>n>>m>>k;
28         for(int i=0; i<n; i++) {
29             a[i]=0; f[i]=i;
30         }
31         int maxn=0, maxx=0;
32         for(int x,y,i=0; i<m; i++) {
33             cin>>x>>y;
34             Union(x, y);
35             if(x==y) continue;
36             a[x]++, a[y]++;
37             if(a[x]>maxn) maxx=x, maxn=a[x];
38             if(a[y]>maxn) maxx=y, maxn=a[y];
39         }
40         
41         int root = find(maxx);
42         for(int i=0; i<n; i++) {
43             int t = find(i);
44             if(t==i && t!=root) maxn++;
45         }
46 
47         int dir = n-maxn-1;
48         if(k>=dir) maxn=n-1;
49         else maxn+=k;
50         
51         if(!n) maxn = 0;
52         cout<<maxn<<endl;
53     }
54     return 0;
55 }

1004 p1m2

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6383

找出数列中最大值和最小值,二分枚举答案,对于每一个答案都循环计算一次;思想同二分查找,每次答案所在区间缩小一半;

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 #define min(a,b) a>b?b:a
 6 #define LL long long 
 7 const int N = 300005;
 8 LL T, n, a[N];
 9 
10 int main()
11 {
12     ios::sync_with_stdio(false);
13     cin>>T;
14     while(T--)
15     {
16         cin>>n;
17         LL minn=1e9, maxn=-1;
18         for(int i=0; i<n; i++) {
19             cin>>a[i];
20             minn = min(a[i], minn);
21             maxn = max(a[i], maxn);
22         }
23         
24         while(minn <= maxn) {
25             LL mid = (minn+maxn)/2, tmp = 0;
26             for(int i=0; i<n; i++) {
27                 if(a[i]>mid) tmp += (a[i]-mid)/2;
28                 else tmp += a[i]-mid;
29             }
30             if(tmp<0)
31                 maxn = mid-1;
32             else
33                 minn = mid+1;
34         }
35         cout<<maxn<<endl;
36     }
37     
38     return 0;
39 }

1006 rect

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6385

假设有交叉线的情况存在,对这种假设列满足条件的不等式,发现矛盾,所以不存在交叉线情况;

 1 #include<iostream>
 2 using namespace std;
 3 
 4 #define min(a,b) a>b?b:a
 5 #define LL long long
 6 int T;
 7 LL mx, my, n;
 8 
 9 int main()
10 {
11     cin>>T;
12     while(T--) {
13         cin>>mx>>my>>n;
14         
15         LL ans=0;
16         int x,y;
17         for(int i=0; i<n; i++) {
18             cin>>x>>y;
19             if(x<=mx/2 && y<=my/2) ans += min(x,y);
20             else if(x>=mx/2 && y<=my/2) ans += min(mx-x, y);
21             else if(x>=mx/2 && y>=my/2) ans += min(mx-x, my-y);
22             else if(x<=mx/2 && y>=my/2) ans += min(x, my-y);
23         }
24         cout<<ans<<endl;
25     }
26     
27     return 0;
28 }
原文地址:https://www.cnblogs.com/liubilan/p/9466760.html