2015年百度之星程序设计大赛 - 初赛(1)

总结 ->过往

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:\n",++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!\n");
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!\n");
62                  break;
63             }
64             tmp=a[idx];
65             if (tmp>=Max)
66             {
67                  printf("why am I so diao?\n");
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\n");
               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\n",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:\n",++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\n",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:\n",++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\n",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:\n",_);
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\n",ans);
139      }
140     return 0;
141 }
View Code

 

posted on 2015-05-31 10:10  forgot93  阅读(538)  评论(0编辑  收藏  举报

导航