您的位置:首页 > 其它

Codeforces 246C Little Girl And Maximum 差分

2017-02-18 14:08 519 查看
点击打开链接

题意:n个数,m次询问 n,m<=1e5 问初始时如何打乱数组的顺序 使得查询的累加和最大?

最后的累加和可以写为:ans=segma(a[i]*f[i])

每次询问l,r时 如何快速计算f? 

用线段树区间更新使f[l]~f[r]同时加上1,最后单点查询计算出f,比较麻烦

利用差分,每次更新时:c[l]++,c[r+1]-- 最后计算i的前缀和,即可求出i被包含在多少条线段(询问)中啦 

ai<aj bi<bj;

因为a[i]·b[j]+a[j]·b[i]-a[i]·b[i]-a[j]·b[j] = b[j]·(a[i]-a[j])+b[i]·(a[j]-a[i])=(b[j]-b[i])*(a[i]-a[j])<=0.

ans尽量大则大的a[i]和大的f[i]相乘即可 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=2e5+20;
const ll mod=19999997;
ll a
,f
,c
;// f[i] 第i个元素被查询到的次数
int n,m;
int main()
{
while(cin>>n>>m)
{
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
f[l]++;//差分
f[r+1]--;
}
f[0]=0;
for(int i=1;i<=n;i++)
f[i]=f[i]+f[i-1];//不包含i的线段k,计算前缀和时被消去,(.lk..rk.l..i..r.. )
sort(f+1,f+1+n);
sort(a+1,a+1+n);
ll ans=0;
for(int i=1;i<=n;i++)
{
ans+=a[i]*f[i];
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: