noip 2011 提高 day2(18.04.14)

   第一题杨辉三角形结合推论应该是非常简单的,但是在递推的时候忽略了数据范围(准确地说应该是算错了...),没有mod也没有开long long就直接wa掉7个点...//惨痛教训...

   第二题一道十分显然的二分,前缀和思想非常重要!! 类似树状数组的前缀和可以有效地将累加变为o(1)查询;当然还有一个值得注意的地方,整数的二分要考虑正确答案左右的大小,即需要将最终mid左右两边的值算出的答案进行比较。 正确性十分显然就不再赘述。。

   第三题是一道贪心。贪心法则十分具有迷惑性,并不是经过的越多的边就要用加速器,而是下车时才能获得实际收益。教程如下:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
   int n,m,k;
   int d[10001];
   int t[10001],a[10001],b[10001];
   int latest[10001];
   int arrive[10001];
   int sum[10001];
   int next[10001];
   int ans=0;
   int qqq;
   int dd;
   int maxl;
   int maxint=1000000000;    
   int max(int a,int b){return a>b?a:b;}
   int min(int a,int b){return a<b?a:b;}
   int main()
      {
       freopen("bus.in","r",stdin);
       freopen("bus.out","w",stdout);
       memset(latest,0,sizeof(latest));
       memset(sum,0,sizeof(sum));
       scanf("%d%d%d",&n,&m,&k);
       for(int i=1;i<=n-1;i++)
           scanf("%d",&d[i]);
       for(int i=1;i<=m;i++)
          {
           scanf("%d%d%d",&t[i],&a[i],&b[i]);
           if(t[i]>latest[a[i]])
               latest[a[i]]=t[i];
           sum[b[i]]++;
           }
       
       for(int i=1;i<=n;i++) 
           sum[i]+=sum[i-1];
       while(1){
            maxl=1;
            //计算arrive[i]  表示bus到达第i个景点的时间。
            arrive[1]=0;
            for(int i=2;i<=n;i++)
               arrive[i]=max(arrive[i-1],latest[i-1])+d[i-1];
            //计算next[i]表示在第i个景点后离第i个景点最近的满足
//latest[i]>=arrive[i](即bus到的时间不比最后到的乘客时间晚)的景点。
            //即第i个景点到next[i]-1个景点均是bus到的时间比最后到的乘客时间晚
            next[n]=n;
            for(int i=n-1;i;i--){
                next[i]=next[i+1];
                if(arrive[i+1]<=latest[i+1])
                   next[i]=i+1;
                }
            //贪心选择最优的一条边操作,一次操作可以直接使d[i]变为0
            while(!d[maxl]&&maxl<=n-1)
                  maxl++;
            if(maxl==n||k==0)
               break;
            for(int i=maxl+1;i<=n-1;i++)
               if(d[i]&&sum[next[maxl]]-sum[maxl]<sum[next[i]]-sum[i])//选择加速要让最多的人受益,只有到达了目的地的乘客才是真正受益。经过的乘客不一定受益,因为虽然现在加速了,但后面可能因为等晚到的乘客,而没有真正受益!
                  maxl=i;
            if(sum[next[maxl]]-sum[maxl]==0)
               break;
            dd=maxint;
            for(int i=maxl+1;i<=next[maxl]-1;i++)
               dd=min(dd,arrive[i]-latest[i]);    
            dd=min(dd,k);
            dd=min(dd,d[maxl]);
            k-=dd;
            d[maxl]-=dd;
            }
       for(int i=1;i<=m;i++)
           ans+=arrive[b[i]]-t[i];
       printf("%d",ans);
       fclose(stdin);
       fclose(stdout);
       return 0;

       }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值