2019HDU多校第十场

(撒花!二十场打完了。虽然题解(riji)咕咕咕了好几场。

1003 Valentine's Day

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6693

题意:每个物品有一个能够快乐的概率$p_i$,问在$n$个物品中选择若干个,能够只快乐一次的最大概率为多少。

数据范围:$1<=n<=10000$。

分析:排序,依此选择最大,次大,……然后什么一个式子就过了?

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e4+100;
 4 double p[maxn];
 5 bool cmp(double A,double B) {return A>B;}
 6 void rua()
 7 {
 8     int n;scanf("%d",&n);
 9     double ans=0.0,res=0.0,tmp=1.0;
10     for (int i=1;i<=n;i++) scanf("%lf",&p[i]);
11     sort(p+1,p+1+n,cmp);
12     if(p[1]==1.0) {printf("%.12lf\n",p[1]);return;}
13     for (int i=1;i<=n;i++) 
14     {
15         double kk=1.0-p[i];
16         tmp*=kk;
17         double tt=p[i]/kk;
18         res+=tt;
19         ans=max(ans,tmp*res);
20     }
21     printf("%.12lf\n",ans);
22     return;
23 }
24 int main()
25 {
26     int t;scanf("%d",&t);
27     while(t--) rua();
28     return 0;
29 }
1003

1005 Welcome Party

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6695

题意:有$n$个人,每个人有两个值$a_i,b_i$,每个人只能属于集合A(只参考$a_i$)或集合B(只参考$b_i$),定义每个集合的价值为集合中的最大值。要求求两个集合价值的最小差值。

数据范围:$2<=n<=100000,0<=a_i,b_i<=10^{18}$。

分析:考虑怎么维护最小的差值。对于$a_i$从小到大排序,然后每次枚举集合A的最大值。

假设$a_i$为集合A的最大值,那么在$i$之后的数一定在集合B内,这个最大值可以用过预处理得到。假设这个最大值为$bb$。

那么对于$i$之前的数我们就考虑能不能归到集合B,使得再找到一个更优的答案即可。

如果之前的$b_i<=bb$,对于答案没有贡献。那么我们需要找的是一个数距离$a_i$更近,且大于$bb$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e5+10;
 5 const ll INF=1e18+10;
 6 struct node{ll x,y;}a[maxn];
 7 bool cmp(node p,node q){return p.x<q.x;}
 8 set<ll>s;   ll mx[maxn];
 9 int main(){
10     int t,n;scanf("%d",&t);
11     while (t--){
12         scanf("%d",&n);
13         for (int i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].y);
14         sort(a+1,a+1+n,cmp);
15         ll mxx=0; mx[n+1]=0;
16         for (int i=n;i>=1;i--){
17             if (a[i].y>mxx) mxx=a[i].y;
18             mx[i]=mxx;
19         }
20         s.clear();ll ans=INF;
21         for (int i=1;i<=n;i++){
22             ll aa=a[i].x,bb=mx[i+1];
23             if(i!=n) ans=min(ans,abs(bb-aa));
24             if(!ans) break;
25             if (bb>aa||s.empty()) {s.insert(a[i].y);continue;}
26             auto it=s.lower_bound(aa);
27             if(it!=s.end()) ans=min(ans,abs((*it)-aa));
28             if(it!=s.begin()){
29                 --it;
30                 ans=min(ans,abs((*it)-aa));
31             }
32             if(!ans) break;
33             s.insert(a[i].y);
34         }
35         printf("%lld\n",ans);
36     }
37     return 0;
38 }
1005

1009 Block Breaker

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6699

题意:有一个大小为$n*m$的方格矩阵,击打$q$次,问每次击打掉落的块数为多少。每个块掉落的定义为左右至少有一个块不存在,上下至少有一个块不存在。

数据范围:$1<=n,m<=2000,1<=q<=100000$。

分析:开始觉得迷惑为什么大家都会。然后仔细想了想,最多就$n*m$个块会被击落,如果这个块已经不在了,答案就是0,也不会影响到别的块。那么每次就考虑击打一个块能够影响到周围的情况。宽搜就好啦!

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2007;
 4 int vis[maxn][maxn];
 5 int n,m,q;
 6 int dx[]={0,0,1,-1};
 7 int dy[]={1,-1,0,0};
 8 struct node{int x,y;};
 9 bool check(int x,int y)
10 {
11     int numx=0,numy=0;
12     for (int i=0;i<4;i++)
13     {
14         int xx=x+dx[i],yy=y+dy[i];
15         if (xx<1 || xx>n || yy<1 || yy>m) continue;
16         if (vis[xx][yy]){
17             if (i==0 || i==1) numx++; 
18             else numy++;
19         }
20     }
21     return (numx>=1 && numy>=1);
22 } 
23 
24 int bfs(int x,int y)
25 {
26     queue<node> Q;
27     node cur,nex;
28     cur.x=x;cur.y=y;
29     Q.push(cur);vis[x][y]=1;
30     int res=0;
31     while (!Q.empty())
32     {
33         cur=Q.front();Q.pop(); res++; 
34         for (int i=0;i<4;i++)
35         {
36             int xx=cur.x+dx[i],yy=cur.y+dy[i];
37             if (xx<1 || xx>n || yy<1 || yy>m) continue;
38             if(check(xx,yy) && !vis[xx][yy])
39             {
40                 nex.x=xx;nex.y=yy;
41                 Q.push(nex);
42                 vis[xx][yy]=1;
43             }
44         }
45     }
46     return res;
47 }
48 void rua()
49 {
50     scanf("%d%d%d",&n,&m,&q);
51     for (int i=0;i<=n;i++) for (int j=0;j<=m;j++) vis[i][j]=0;
52     while (q--)
53     {
54         int x,y;scanf("%d%d",&x,&y);
55         int ans;
56         if(vis[x][y]) ans=0;
57         else ans=bfs(x,y);
58         printf("%d\n",ans);
59     }
60     return;
61 }
62 int main()
63 {
64     int t;scanf("%d",&t);
65     while(t--) rua();
66     return 0;
67 }
1009

1011 Make Rounddog Happy

题解传送:https://www.cnblogs.com/changer-qyz/p/11392174.html

 

 

posted @ 2019-08-22 02:48  Changer-qyz  阅读(391)  评论(0编辑  收藏  举报