• noip模拟赛 思考熊的马拉松


    【题目描述】

    今年,n只思考熊参加了清华大学校园马拉松比赛。马拉松的赛道是环形的,每圈
    的长度是A,完成比赛需要跑L圈。
    比赛中,甲领先乙很长距离,绕过一圈或多圈后从后面追上了乙的现象叫做“套
    圈”。套圈现象非常常见,例如:跑得比谁都快的saffah熊可以套某些熊L-1圈;
    ufozgg熊经常进行日常耐力训练,套圈次数和被套圈次数基本持平;而Mulab作为一
    只老年熊,则是被套L-1圈的那种。
    与人不同的是,思考熊在跑步时都是匀速运动。wyx熊是这次比赛的计时员,他
    统计了参赛的n只熊的速度v1v2,......,vn(其中最大的一个是saffah熊的速度)。现在
    wyx熊希望你告诉他,当速度最快的saffah熊到达终点时,场上所有熊中总共发生了
    多少次套圈现象。
    注意:在saffah熊刚刚到达终点那一刻,如果甲恰好追上了乙,此时也算作甲将乙
    套圈。

    【输入格式】

    从文件running.in中读入数据。
    输入的第一行包含2个整数T;C,分别表示这个测试点内数据的组数和这个测试
    点的编号。对于所有测试点,保证T = 10
    每组数据的第一行包含3个正整数n;A;L,分别表示思考熊的只数,跑道每圈的长
    度和完成比赛所需要的圈数。保证A;L<10^8
    第二行包含n个正整数v1v2,......,vn,表示每只思考熊的速度。保证这些数互不
    相同。

    【输出格式】

    输出到文件running.out中。
    输出T行,分别表示每组数据中,所有熊发生的套圈总次数。

    【样例输入】

    4 0
    2 1000 15
    2 5
    2 1000 13
    9 4
    5 1000 10
    8 10 2 5 6
    5 1000 17
    8 10 2 5 7

    【样例输出】

    9
    7
    38
    61

    【数据范围】

    n<=105,vi<=108

    【题解】

    套圈的圈数只取决于每个人跑了多少圈,所以答案为两两之间的圈数差向下取整
    因为有圈数小数部分,所以无法通过前缀和O(n)计算
    但是,我们可以把小数部分和整数部分分开做
    整数部分用前缀和维护圈数,如果小数部分的差小于0,就再减一
    比如一个跑了5.1圈,一个4.9圈,他们整数部分差为5-4=1,但是因为小数部分0.1-0.9<0,所以需要减一
    所以需要找出两个数i,j,整数部分i>j,但小数i<j
    这就是逆序对棵题了,树状数组就能搞定。
    还有一个小优化,因为跑的圈数是l*vi/vmax,分母都相同,可以全部去掉转化成整数计算,避免精度误差

    (之前用小数存被精度误差卡成狗了.......)

    【代码】

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<set>
    using namespace std;
    #define f(i,n) for(int i=1;i<=(n);i++)
    #define ll long long
    #define INF 1<<30
    #define N 100010
    #define c 32123
    ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n;
    ll v[N],f,l;
    struct xj
    {
    	double n;
    	int i;
    }z[N];
    double s;
    bool cmp(xj a,xj b)
    {
    	if(a.n==b.n)return a.i>b.i;
    	return a.n>b.n;
    }
    int szsz[N];
    int lowbit(int x)
    {
    	return x&-x;
    }
    void ass(int k)
    {
    	while(k<=n)
    	{
    		szsz[k]++;
    		k+=lowbit(k);
    	}
    }
    int qj(int k)
    {
    	int ans=0;
    	while(k>0)
    	{
    		ans+=szsz[k];
    		k-=lowbit(k);
    	}
    	return ans;
    }
    int main()
    {
    	freopen("running.in","r",stdin);
    	freopen("running.out","w",stdout);
    	int t,C;
    	scanf("%d%d",&t,&C);
    	while(t--)
    	{
    	    scanf("%d%lld%lld",&n,&f,&l);
    		f(i,n)v[i]=read();
    		sort(v+1,v+n+1);
    		ll ans=0,sum=0;
    		f(i,n)
    		{
    			ll temp=l*v[i]/v[n];
    			ans+=(i-1)*temp-sum;
    			sum+=temp;
    			z[i].n=l*v[i]-temp*v[n];
    			z[i].i=i;
    		}
    		memset(szsz,0,sizeof(szsz));
    		sort(z+1,z+n+1,cmp);
    		f(i,n)
    		{
    			ans-=qj(z[i].i);
    			ass(z[i].i);
    		}
    		printf("%lld\n",ans);
    	}
    }
    
  • 相关阅读:
    vs2015安装出问题
    Cookie的Domain属性
    IE6 PNG不透明问题 (只解决img标签的图片)
    C#aspx页面前台使用<%=%>无法取到后台的值
    题解【洛谷P2003】平板
    题解【洛谷P2070】刷墙
    题解【洛谷P1083】[NOIP2012]借教室
    CSP-J/S 2019 游记
    题解【洛谷P1967】[NOIP2013]货车运输
    “美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学) E 小花梨的数组 线段树
  • 原文地址:https://www.cnblogs.com/qwerfcxs/p/7802638.html
Copyright © 2020-2023  润新知