首页 > 代码库 > 灰姑娘的水晶鞋(NOIP模拟赛Round 7)

灰姑娘的水晶鞋(NOIP模拟赛Round 7)

【问题描述】

传说中的水晶鞋有两种颜色:左边的水晶鞋是红色,右边的是蓝色,据说穿上它们会有神奇的力量。

灰姑娘要找到她所有的n双水晶鞋,它们散落在一条数轴的正半轴上,坐标各不相同,每双水晶鞋还有一个权值wi。灰姑娘一开始位于原点,当她将其中一双水晶鞋拿回原点时,那双水晶鞋就改变了它原来的位置,这时还固定于数轴正半轴上的那些水晶鞋就会因为共鸣而发生升华现象。升华过程的损耗为:被取走的水晶鞋发生的位移*(还固定在数轴正半轴上的编号与被取走的水晶鞋编号对m取模同余的水晶鞋的w权值之和)。举个例子:

技术分享

现在灰姑娘想得到所有的水晶鞋,但是她又希望升华的消耗最少,因为她希望能在秋之国即将举办的夏日祭里赢得更多的掌声。所以她找到了你帮忙。

【数据范围】

对于25%的数据,n<=10;

对于另外5%的数据,m=n;

对于60%的数据,n<=1000;

对于另外10%的数据,m=1;

对于100%的数据,0<n,m<=200,000,0<坐标范围<=10^9,0<ai,bi<=10^4。

——————————————我是分割线——————————————

好吧,这道题一看就是贪心,但是怎么贪呢?换句话说,怎么排序呢?

首先我们假设取i比取j更优

则得到下列不等式

技术分享

所以我们只需要按照这个不等式排序就好啦

注意!本题会爆long long 所以要开2个long long进行处理!

下面贴代码

#include<cstdio>
#include<algorithm>
#define INF 1000000000000000000
using namespace std;
int d[200005],w[200005];
int paixu[200005];
unsigned long long sum[200005];
unsigned long long ans1,ans2;
int n,m;
bool cmp(int a,int b){return 1LL*d[a]*w[b]<1LL*d[b]*w[a];}
void add(unsigned long long a){ans2+=a;if(ans2>INF)ans1++,ans2-=INF;}
int main(){
    freopen("crystal.in","r",stdin);
    freopen("crystal.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&d[i],&w[i]);
        paixu[i]=i; 
        sum[i%m]+=w[i];
    }
    sort(paixu+1,paixu+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
        sum[paixu[i]%m]-=w[paixu[i]];
        add(d[paixu[i]]*sum[paixu[i]%m]);
    }
    if(ans1)printf("%lld%018lld",ans1,ans2);
    else printf("%lld\n",ans2);
    fclose(stdin);
    fclose(stdout);
}

 

灰姑娘的水晶鞋(NOIP模拟赛Round 7)