P2367 语文成绩
思路:
模板题,用前缀和,差分求解。
构造一个差分数组,使得每一个数组元素加上之前的所有数组元素,等于本元素位置所对应的学生成绩,求出最小值输出即可
代码:
时间复杂度o(n)
#include<iostream>
using namespace std;
const int N=1e7+10;
int e[N],s[N];
void add(int l,int r,int c)
{
s[l]+=c;
s[r+1]-=c;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>e[i];
add(i,i,e[i]);
}
while (m--)
{
int l,r,c;
cin>>l>>r>>c;
add(l,r,c);
}
int emin=110;
for(int i=1;i<=n;i++)
{
s[i]+=s[i-1];
emin=min(emin,s[i]);
}
cout<<emin<<endl;
return 0;
}
P3397 地毯
思路:
和上题一样,差分,不同的是本题是二维差分,构造一个数组,在起始和结束的位置加一减一,之后前缀和相加,就行了。
代码:
时间复杂度o(n^2)
#include <iostream>
using namespace std;
const int N=1010;
int s[N][N];
void insert(int x1,int y1,int x2,int y2 )
{
s[x1][y1]+=1;
s[x1][y2+1]-=1;
s[x2+1][y1]-=1;
s[x2+1][y2+1]+=1;
}
int main()
{
int n,m;
cin>>n>>m;
while (m--)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
insert(x1,y1,x2,y2);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
cout<<s[i][j]<<' ';
}
cout<<endl;
}
return 0;
}
P1496 火烧赤壁
思路:
本题不能采用差分,前缀和,应为a,b的范围为-2的31次方~2的31次方,而2的30次方就是1e9,计算机计算一秒的次数也就是1e9,所以采用差分,前缀和的话,由于最后需要遍历,求和,所以会超时。
故本题可以采用区间和并的方法,存储每一个着火点的范围,然后将它们合并到一起,最后遍历计算和即可。
代码:
时间复杂度o(n)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N=1e5+10;
typedef pair<int,int> PII;
vector<PII> res,ans;
int main()
{
int n;
cin>>n;
while (n--)
{
int l,r;
cin>>l>>r;
res.push_back({l,r});
}
sort(res.begin(),res.end());
int l=-1e9,r=-1e9;
for(auto item:res)
{
if(item.first>r)
{
if(l!=-1e9) ans.push_back({l,r});
l=item.first,r=item.second;
}
else r=max(r,item.second);
}
if(l!=-1e9) ans.push_back({l,r});
int answer=0;
for(auto item:ans)
{
answer+=item.second-item.first;
}
cout<<answer<<endl;
return 0;
}