zoukankan      html  css  js  c++  java
  • 2015年百度之星程序设计大赛

    总结 ->过往

    1001:贪心思路,每次尽量选靠后的。

              因为x ,x+1, x+2 如果选了x+2,效果是比x更换的因为我后面的值是在0-k之中,只有尽量k减少的次数更少。

              所以现在假设在x ,我们找y<x+k 找到最大的y;

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include<math.h>
     5 #include <algorithm>
     6 #include <set>
     7 typedef long long ll;
     8 using namespace std;
     9 #define N 1023456
    10 #define inf 0x3f3f3f3
    11 typedef long long ll;
    12 
    13 ll a[N];
    14 int n,m,k;
    15 
    16 int pan(int lxl,int rr,ll x)
    17 {
    18   int flag=0;
    19   int l=lxl,r=rr;
    20 
    21   for (int _=1;_<=50;_++)
    22   {
    23       int mid=(l+r)/2;
    24       if (a[mid]<=x)
    25       {
    26           flag=mid;
    27           l=mid;
    28       }
    29       else r=mid;
    30   }
    31   return flag;
    32 }
    33 
    34 int main()
    35 {
    36     int T;
    37     scanf("%d",&T);
    38     int cas=0;
    39     while (T--)
    40     {
    41 
    42         printf("Case #%d:
    ",++cas);
    43         scanf("%d%d%d",&n,&m,&k);
    44 
    45         ll Max=0;
    46         for (int i=1;i<=n;i++)
    47         scanf("%I64d",&a[i]),Max=max(Max,a[i]);
    48         sort(a+1,a+n+1);
    49         int  idx=pan(1,n,m);
    50         if (!idx)
    51         {
    52             printf("madan!
    ");
    53             continue;
    54         }
    55         ll tmp=a[idx];
    56         while (1)
    57         {
    58             idx=pan(idx+1,n,tmp+k);
    59             if (idx==0)
    60             {
    61                  printf("madan!
    ");
    62                  break;
    63             }
    64             tmp=a[idx];
    65             if (tmp>=Max)
    66             {
    67                  printf("why am I so diao?
    ");
    68                  break;
    69             }
    70             k--;
    71         }
    72     }
    73     return 0;
    74 }
    View Code

    1002:这道题给了直接模拟做,关键点事快速找到 1->k,2->k+1,3->k+2;中是否有连续的数;

             我们可以先求出区间最大值Max,Min;

             首先判断Max-Min==k-1;

             然后用一个数组计入数是否出现两次。用map HASH 注意map HASH预先处理一下,因为在线做毕竟多 一个log

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #include <cmath>
    #include <iostream>
    #include <map>
    using namespace std;
    #define N 10011
    
    int a[N],b[N];
    int n,m,nn;
    map<int,int>mp;
    
    int dpmin[N][17];
    int dpmax[N][17];
    int cnt[N];
    
    void init()
    {
        for (int i=1;i<=n;i++) dpmin[i][0]=dpmax[i][0]=a[i];
        int mm=log2(n);
        for (int j=1;j<=mm;j++)
        for (int i=1;(i+(1<<j)-1)<=n;i++)
        dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]),
        dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);
    }
    
    int rmqmax(int l,int r)
    {
        int k=log2(r-l+1);
        return max(dpmax[l][k],dpmax[r-(1<<k)+1][k]);
    }
    int rmqmin(int l,int r)
    {
        int k=log2(r-l+1);
        return min(dpmin[l][k],dpmin[r-(1<<k)+1][k]);
    }
    int f[N];
    
    int main()
    {
           scanf("%d%d",&n,&m);
           mp.clear();
           puts("Case #1:");
           for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
           sort(b+1,b+n+1);
           int  nn=unique(b+1,b+n+1)-b-1;
           for (int i=1;i<=nn;i++) mp[b[i]]=i;
           for (int i=1;i<=n;i++) f[i]=mp[a[i]];
           init();
           while (m--)
           {
               int k;
               scanf("%d",&k);
               if (k>n)
               {
                   printf("0
    ");
                   continue;
               }
               memset(cnt,0,sizeof(cnt));
               int ans=0;
               int chong=0;
               for (int i=1;i<=k;i++)
               {
                   int idx =f[i];
                   cnt[idx]++;
                   if (cnt[idx]==2) chong++;
    
               }
               int _max=rmqmax (1,k);
               int _min=rmqmin (1,k);
    
               if (!chong&&_max-_min==k-1) ans++;
    
               for (int i=k+1;i<=n;i++)
               {
                   int x =f[i-k];
                   int y =f[i];
                       cnt[x]--;
                       if (cnt[x]==1) chong--;
    
                       cnt[y]++;
                       if (cnt[y]==2) chong++;
    
                   _max=rmqmax(i-k+1,i);
                   _min=rmqmin(i-k+1,i);
                   if (!chong&&_max-_min==k-1) ans++;
               }
               printf("%d
    ",ans);
           }
       return 0;
    }

    1003:水

    二分答案,判断是否可行

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include<math.h>
     5 #include <algorithm>
     6 typedef long long ll;
     7 using namespace std;
     8 #define N 1023456
     9 #define inf 0x3f3f3f3
    10 
    11 int a[N],b[N];
    12 int n;
    13 
    14 int pan(int x)
    15 {
    16     for (int i=1;i<=n;i++) b[i]=a[i];
    17     b[1]=b[1]-x;
    18 
    19     for (int i=2;i<=n;i++)
    20     {
    21         int tmpx=b[i]-x;
    22         int tmpy=b[i]+x;
    23         if (b[i-1]>=tmpy) return 0;
    24         b[i]=max(tmpx,b[i-1]+1);
    25     }
    26     return  1;
    27 }
    28 
    29 int main()
    30 {
    31     int T;
    32     scanf("%d",&T);
    33     int cas=0;
    34     while (T--)
    35     {
    36         printf("Case #%d:
    ",++cas);
    37         scanf("%d",&n);
    38         for (int i=1;i<=n;i++)
    39         scanf("%d",&a[i]);
    40 
    41         int l=0,r=1234567;
    42         for (int _=1;_<=60;_++)
    43         {
    44             int mid=(l+r)/2;
    45             if (pan(mid)) r=mid;
    46             else l=mid;
    47         }
    48         printf("%d
    ",r);
    49     }
    50     return 0;
    51 }
    View Code

    1004:

    很多平衡树,可是我并不会写treap,splay;

    于是离线处理,BIT处理前缀和

    具体做法:一个数记录当前管道里面有多少个数,用来求中位数;

                离散所有出现的数,相对应的记录下标;

                对 in 的数 树状数组更新 1,

                对out 的数更新 -1;

                query的数比较麻烦,我们可以二分求出最小的x sum(x)==此刻中位数的答案{说的乱}

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include<cmath>
      5 #include <algorithm>
      6 
      7 
      8 typedef long long ll;
      9 using namespace std;
     10 #define N 102345
     11 #define inf 0x3f3f3f3
     12 typedef long long ll;
     13 int type[N],a[N],b[N],f[N];
     14 
     15 int n,num;
     16 
     17 
     18 int lowbit(int x)
     19 {
     20     return x&(-x);
     21 }
     22 
     23 int sum(int x)
     24 {
     25     int s=0;
     26     while (x)
     27     {
     28         s+=f[x];
     29         x-=lowbit(x);
     30     }
     31     return s;
     32 }
     33 
     34 void update(int x,int val)
     35 {
     36     while (x<=num)
     37     {
     38         f[x]+=val;
     39         x+=lowbit(x);
     40     }
     41 }
     42 
     43 
     44 int pan(int l,int r,int tans)
     45 {
     46     for (int _=1;_<=50;_++)
     47     {
     48         int mid=(l+r)>>1;
     49         if (sum(mid)>=tans) r=mid;
     50         else l=mid;
     51     }
     52     return r;
     53 }
     54 
     55 int main()
     56 {
     57 
     58     int cas=0;
     59     while (scanf("%d",&n)!=EOF)
     60     {
     61         printf("Case #%d:
    ",++cas);
     62         memset(f,0,sizeof(f));
     63         char s[10];
     64         num=0;
     65         
     66         for (int i=1;i<=n;i++)
     67         {
     68             int x;
     69             scanf("%s",s);
     70             if (s[0]=='i')
     71             {
     72                 scanf("%d",&x);
     73                 type[i]=1;
     74                 a[++num]=x;
     75 
     76             }
     77             else if (s[0]=='o')
     78             type[i]=3;
     79             else type[i]=2;
     80         }
     81         
     82         for (int i=1;i<=num;i++) b[i]=a[i];
     83         sort(b+1,b+num+1);
     84 
     85         int p=1;
     86         int num1=1;
     87         int fuck=0;
     88 
     89         for (int i=1;i<=n;i++)
     90         {
     91             if (type[i]==1)
     92             {
     93                 int idx=lower_bound(b+1,b+num+1,a[num1])-b;
     94                 update(idx,1);
     95                 num1++;
     96                 fuck++;
     97             }
     98             else if (type[i]==2)
     99             {
    100                 int tmp=floor(fuck/2)+1;
    101                 
    102                 int  ans=b[pan(1,num,tmp)];
    103                 printf("%d
    ",ans);
    104             }
    105             else
    106             {
    107               fuck--;
    108               int idx=lower_bound(b+1,b+num+1,a[p])-b;
    109               update(idx,-1);
    110               p++;
    111             }
    112         }
    113     }
    114     return 0;
    115 }
    View Code        

     请结合 代码

     这题还有2个set的 写法,因为是求得中位数。

    1005:写不出来

    10056:模板,做法是 一个矩形覆盖所有出现的点。求次矩形最小面积

                 凸包求,加旋转卡壳(具体百度其他)

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 #define MAXN 51000
      8 #define EPS 1e-10
      9 
     10 using namespace std;
     11 
     12 int n;
     13 double minsqr; //minsqr=最小矩形面积
     14 
     15 int dcmp(double x)
     16 {
     17     if(fabs(x)<EPS) return 0;
     18     if(x>-EPS) return 1;
     19     return -1;
     20 }
     21 
     22 struct Point
     23 {
     24     double x,y;
     25     Point(){}
     26     Point(double _x,double _y):x(_x),y(_y){}
     27     void read()
     28     {
     29         scanf("%lf%lf",&x,&y);
     30     }
     31 }points[MAXN],stack[MAXN<<1],ans[10]; //ans保存最小覆盖矩形的四个顶点
     32 
     33 Point operator-(Point a,Point b)
     34 {
     35     return Point(a.x-b.x,a.y-b.y);
     36 }
     37 
     38 Point operator*(Point a,double b)
     39 {
     40     return Point(a.x*b,a.y*b);
     41 }
     42 
     43 Point operator+(Point a,Point b)
     44 {
     45     return Point(a.x+b.x,a.y+b.y);
     46 }
     47 
     48 double cross(Point a,Point b,Point c) //a->b 叉积 a->c
     49 {
     50     return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
     51 }
     52 
     53 double dot(Point a,Point b,Point c) //a->b 点积 b->c
     54 {
     55     return (b.x-a.x)*(c.x-b.x)+(b.y-a.y)*(c.y-b.y);
     56 }
     57 
     58 double dist(Point a,Point b)
     59 {
     60     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     61 }
     62 
     63 int top=0;
     64 
     65 bool cmp(Point a,Point b)
     66 {
     67     if(!dcmp(a.x-b.x)) return a.y<b.y;
     68     return a.x<b.x;
     69 }
     70 
     71 bool operator<(Point a,Point b)
     72 {
     73     if(!dcmp(a.y-b.y)) return a.x<b.x;
     74     return a.y<b.y;
     75 }
     76 
     77 void Graham()
     78 {
     79     sort(points+1,points+n+1,cmp);
     80     for(int i=1;i<=n;i++) //下凸壳
     81     {
     82         while(top>=2&&dcmp(cross(stack[top-1],stack[top],points[i])<=0)) top--;
     83         stack[++top]=points[i];
     84     }
     85     int tmp=top;
     86     for(int i=n-1;i>=1;i--) //上凸壳
     87     {
     88         while(top>=tmp+1&&dcmp(cross(stack[top-1],stack[top],points[i])<=0)) top--;
     89         stack[++top]=points[i];
     90     }
     91     top--; //栈顶显然是points[1],重复了一次,将重复的丢掉
     92 }
     93 
     94 void rotcalip() //旋转卡壳
     95 {
     96     int left=1,right=1,up=1; //左、右、上三个点
     97     for(int i=1;i<=top;i++)
     98     {
     99         while(dcmp(cross(stack[up+1],stack[i],stack[i+1])-cross(stack[up],stack[i],stack[i+1]))>=0) up=up%top+1;
    100         while(dcmp(dot(stack[right+1],stack[i+1],stack[i])-dot(stack[right],stack[i+1],stack[i]))>=0) right=right%top+1;
    101         if(i==1) left=right;
    102         while(dcmp(dot(stack[left+1],stack[i],stack[i+1])-dot(stack[left],stack[i],stack[i+1]))>=0) left=left%top+1;
    103         double L=dist(stack[i],stack[i+1]); //L=点i到i+1的距离
    104         double H=cross(stack[i+1],stack[up],stack[i])/L; //H是矩形的高
    105         double bottom=(fabs(dot(stack[i],stack[i+1],stack[left])/L)+fabs(dot(stack[i],stack[i+1],stack[right])/L));
    106         double nowsqr=bottom*H;
    107         if(nowsqr<minsqr) //这个解比当前答案更优
    108         {
    109             minsqr=nowsqr;
    110             ans[0]=stack[i]+(stack[i+1]-stack[i])*((fabs(dot(stack[i],stack[i+1],stack[right]))/L+L)/L);
    111             ans[1]=ans[0]+(stack[right]-ans[0])*(H/dist(stack[right],ans[0]));
    112             ans[2]=ans[1]+(stack[up]-ans[1])*(bottom/dist(stack[up],ans[1]));
    113             ans[3]=ans[2]+(stack[left]-ans[2])*(H/dist(stack[left],ans[2]));
    114         }
    115     }
    116 }
    117 void init()
    118 {
    119     top=0;
    120 }
    121 
    122 int main()
    123 {
    124      int cas;
    125      scanf("%d",&cas);
    126      for (int _=1;_<=cas;_++)
    127      {
    128          init();
    129     printf("Case #%d:
    ",_);
    130     minsqr=1e12;
    131     scanf("%d",&n);
    132     for(int i=1;i<=n*4;i++)
    133     points[i].read();
    134     n=n*4;
    135     Graham();
    136     rotcalip();
    137     int ans=round(minsqr);
    138     printf("%d
    ",ans);
    139      }
    140     return 0;
    141 }
    View Code
  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/forgot93/p/4541576.html
Copyright © 2011-2022 走看看