P3406 海底高铁
基本思路:
对于其中一小段,我们要么全部买纸票,要么全部刷卡。
所以我们只需要统计每一小段经过的总次数。
如果你暴力模拟统计的话,估计(一定会tle。
接下来来看一组例子:
六个数:
0 0 0 0 0 0
如果想让它从第二个到第五个数全部+1,则为
0 1 1 1 1 0
如果这样模拟+1,所用的时间复杂度为O(N)
如果记为
0 1 0 0 0 -1
所用时间复杂度为O(1)
每一位的值就是其前缀和
0 1 1 1 1 0
这是一维空间内的差分,对于二维空间的差分。
P3397 地毯
如下
0 0 0 0 0 0
0 +1 0 0 0 -1
0 +1 0 0 0 -1
0 +1 0 0 0 -1
0 +1 0 0 0 -1
0 0 0 0 0 0
#include <iostream>
#include <algorithm>
#include <cstring>
#include <math.h>
#include <functional>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <cstdio>
#include <list>
#include <queue>
#include <set>
#include <unordered_map>
#define ll long long
using namespace std;
int k[1100][1100];
int n,m;
int main(){
cin>>n>>m;
int i,a;
int x1,y1,x2,y2;
for(i=0;i<m;i++){
cin>>x1>>y1>>x2>>y2;
for(a=x1;a<=x2;a++){
k[a][y1]++;
k[a][y2+1]--;
}
}
int s;
for(i=1;i<=n;i++){
s=0;
for(a=1;a<=n;a++){
s+=k[i][a];
cout<<s<<" ";
}
cout<<endl;
}
}
上文是关于什么是差分,差分相关思路。
我们可以看到,对于连续的一段数,加上或减去相同的数,通过差分处理可以比模拟更高效地完成任务。
这道题的代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <math.h>
#include <functional>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <cstdio>
#include <list>
#include <queue>
#include <set>
#include <unordered_map>
#define ll long long
using namespace std;
ll n,m;
ll k[100300];//各铁路段的次数(差分记录
ll num[100300];//路径
typedef struct{
ll x,y,z;
}node;
node jo[100300];
int main(){
cin>>n>>m;
ll i;
ll l,r;
for(i=1;i<=m;i++) cin>>num[i];
for(i=1;i<m;i++) {
l=min(num[i],num[i+1]);
r=max(num[i],num[i+1]);
k[l]++;
k[r]--;
}
for(i=1;i<n;i++){
cin>>jo[i].x>>jo[i].y>>jo[i].z;
}
ll s=0;//总和
ll price;//每一段的钱
ll sum=0;//到目前为止的次数
for(i=1;i<n;i++){
sum+=k[i];
price=min(jo[i].x*sum,jo[i].z+jo[i].y*sum);
s+=price;
}
cout<<s;
}
遇事不决用long long
=-=