题目链接:
减成一
存在n个数,每次操作可以任选一个区间使得区间内的所有数字减一。问最少多少次操作,可以让所有数都变成1。(数据保证一定有解。)
题解说的是使用差分法进行解题,但是一直没有弄懂这个差分到底是怎么回事,可能需要多体会一下,但是我感觉就是一个思维题目(一只蒟蒻的理解)
差分,其实就是下一个数值 ,减去上一个数值 。
#include <bits/stdc++.h>
using namespace std;
int f[100010];
int a[100010];
int t,n;
int main()
{
cin >> t;
while(t--)
{
cin >> n;
for(int i=1;i<=n;i++)
{
cin >> a[i];
}
f[1]=a[1]-1;
for(int i=2;i<=n;i++)
{
if(a[i]>a[i-1])
{
f[i]=f[i-1]+a[i]-a[i-1];
}
else
{
f[i]=f[i-1];
}
}
cout << f[n]<< endl;
}
return 0;
}
区间加:把数组a[l]到a[r]都加上k,这种操作称为区间加。
题目链接:
数组
这个暴力一定TLE,所以我们要使用差分的方法。这个的方法可以用数学推出来。具体的可以在纸上模拟一下。
#include <bits/stdc++.h>
using namespace std;
int a[1000010],d[1000010];
int main()
{
int n,m,i,l,r,p,q,L,R;
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
memset(d,0,sizeof(d));
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(i=1;i<=n;i++)
{
d[i]=a[i]-a[i-1];
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&q,&l,&r,&p);
if(q==1)
{
d[l]-=p;
d[r+1]+=p;
}
else
{
d[l]+=p;
d[r+1]-=p;
}
}
scanf("%d%d",&L,&R);
for(i=1;i<=n;i++)
{
a[i]=a[i-1]+d[i];
}
long long int ans=0;
for(i=L;i<=R;i++)
{
ans+=a[i];
}
printf("%lld\n",ans);
return 0;
}
本人目前还是一只蒟蒻,如果有更好的优化方法欢迎评论。