在下面的代码中,b
和c
在计算总和时有助于获取a
的每个元素的计数。我无法掌握它背后的逻辑请帮忙。
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int n,q,l,r;
long long int ans=0;
scanf("%d%d",&n,&q);
vector<int> a(n,0);
vector<int> b(n+1,0);
vector<int> c(n,0);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
while(q--)
{
scanf("%d%d",&l,&r);
b[l-1]++;
b[r]--;
}
c[0]=b[0];
for(int i=1;i<n;i++) c[i]=c[i-1]+b[i];
sort(c.begin(),c.end());
sort(a.begin(),a.end());
for(int i=0;i<n;i++)
{
ans+=a[i]*c[i];
}
printf("%lld",ans);
return 0;
}
请解释b[]
和c[]
在此处的帮助。
答案 0 :(得分:0)
首先要注意的是,正在进行的查询是从1开始的,所以
b[l-1]++;
b[r]--;
实际上在检查员想要检查的第一个索引处递增,并将第一个值递减到他想要检查的范围之外。
现在,b
正在做的是跟踪检查员将要查看的范围,因此,如果我们设置d[i] = sum(b[j]) for j < i
,如果检查员是d[i] = 1
,则0
去看这个面条包,而c
否则(只有1个查询)。 d
所做的事情因此总结了查询中所有不同的c[i-1]
,使其成为之前(b
)和来自b[i]
的新信息的总和({{ 1}})(有点像c[i] = sum(d[i]) for all queries
。
如果您仍然没有看到它,请按照以下方式考虑:当您添加b[i]
时,之前您是0
,并且您刚刚开始新查询, b[i] = 1
和c[i-1] = 0
。现在,c[i] = 1
和b[i+1] = 0
,因为您仍然在范围内。这将一直持续到b[j] = -1
为止,我们仍然有c[j-1] = 1
但总结它们会让我们回到0
,并会保持c[k] = 0
直到新查询开始或结束。您可以很容易地看到在同一范围内b
进行额外更改将使逻辑保持有效。
因此,c[i]
向我们展示了i
面条检查的次数。排序并乘以有序a
,以确保获得最高质量和总和的检查次数。
希望这有帮助!