题目链接https://www.luogu.com.cn/problem/P3406
【解题思路】前缀和、查分
对于其中一小段,我们要么全部买纸票,要么全部刷卡。
所以我们只需要统计每一小段经过的总次数。
如果你暴力模拟统计的话,估计会tle。
怎么快速知道每一段次数呢?
我们回忆一下“借教室”这道题。
如果你高兴的话,可以上线段树或者树装数组——但是没必要。
假设有5段,我们把1到3加上1,可以像图2一样,开头+1,结尾-1。然后2到4加1,如图3.
+1 -1 +1 +1 -1 -1
- - - - - -- - - -- - -- -- - -- --
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
图1 图2 图3
然后呢,我们求出每一项前缀和(就是从前往后加):
1 2 2 1 0
- - - - -
1 2 3 4 5
图4
然后每一段直接贪心比较,然后就有如下代码了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n, m; 4 int p[100005]; 5 int cf[100005]; 6 int a, b, c; 7 long long ans, sum; 8 int main() 9 { 10 cin>>n>>m; 11 for(int i=0; i<m; i++) 12 cin>>p[i]; 13 for(int i=1; i<m; i++){ 14 int l=p[i-1], r=p[i]; 15 if(l>r)swap(l, r); 16 //cout<<l<<"-"<<r<<endl; 17 cf[l]+=1; cf[r]-=1; 18 } 19 for(int i=1; i<n; i++){ 20 sum+=cf[i]; 21 cin>>a>>b>>c; 22 ans+=min(b*sum+c, a*sum); 23 } 24 cout<<ans; 25 return 0; 26 }