洛谷P1315 观光公交 [noip2011D2T3] 贪心

时间:2023-03-10 04:08:39
洛谷P1315 观光公交 [noip2011D2T3] 贪心

正解:贪心

解题报告:

这里是链接!

唔我觉得还是很容易想到是贪心的,这个难就难在怎么贪心

下面列一下常见的几个贪心思想:

1)根据车上的人数排序,人最多的那条路用加速器  

  错误,人数多并不意味着加速的贡献就大.很容易举反例,比如车上有$100$个人都是在$A$站上车,$50$人在$B$站下车$50$人在$C$站下车,然后$B$站有个人来得比车晚.

那根据这个猜想的话就会要$AB$路上加速,但这显然是错的鸭.AB上加速完全没意义欸$QwQ$

2)根据缩短最多人数的路径排序 

  也就是说按照站点一个个来,然后我们很容易得知每个站点有没有迟到的人,没有的话我们就可以在它前面用,然后最后再看哪条路加速加的人最多就欧克了,这个倒序求下可以$O(n)$做.

欧克代码见下

 1 #include<bits/stdc++.h>
2 using namespace std;
3 long long d[1010],t[10010],a[10010],b[10010],off[1010],ti[10010],sum[10010],ans,us[10010],lst[1010];
4 long long read()
5 {
6 char ch=getchar();long long x=0;
7 while(ch>'9' || ch<'0')ch=getchar();
8 while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
9 return x;
10 }
11 int main()
12 {
13 long long n=read(),m=read(),k=read();
14 for(long long i=1;i<n;i++)d[i]=read();
15 for(long long i=1;i<=m;i++)t[i]=read(),a[i]=read(),b[i]=read(),off[b[i]]++,lst[a[i]]=max(lst[a[i]],t[i]);
16 for(long long i=2;i<=n;i++)ti[i]=max(ti[i-1],lst[i-1])+d[i-1];
17 for(long long i=1;i<=n;i++)sum[i]=sum[i-1]+off[i];
18 for(long long i=1;i<=m;i++)ans+=ti[b[i]]-t[i];
19 ti[1]=lst[1];us[n]=us[n-1]=n;
20 while(k--)
21 {
22 for(long long i=2;i<=n;++i)ti[i]=max(ti[i-1],lst[i-1])+d[i-1];
23 for(long long i=n-2;i;--i)
24 {
25 if(ti[i+1]>lst[i+1])us[i]=us[i+1];
26 else us[i]=i+1;
27 }
28 long long nn=0,mm=0;
29 for(long long i=1;i<n;++i)
30 if(sum[us[i]]-sum[i]>nn && d[i])nn=sum[us[i]]-sum[i],mm=i;
31 ans-=nn,d[mm]--;
32 }
33 cout<<ans<<endl;
34 return 0;
35 }

没有注释,但这个想法其实很容易想到的所以我也懒得写注释了,$QwQ$

然后随便优化下可以优化成$n^2$

数据结构优化下似乎可以到$nlogn$,详见$gzy$贪心$ppt$