• 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
    ",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
    ",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
    ",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
    ",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

     

     

  • 相关阅读:
    几种常用的曲线
    0188. Best Time to Buy and Sell Stock IV (H)
    0074. Search a 2D Matrix (M)
    0189. Rotate Array (E)
    0148. Sort List (M)
    0859. Buddy Strings (E)
    0316. Remove Duplicate Letters (M)
    0452. Minimum Number of Arrows to Burst Balloons (M)
    0449. Serialize and Deserialize BST (M)
    0704. Binary Search (E)
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/11392173.html
Copyright © 2020-2023  润新知