• 考分鄙视(exam)


    考分鄙视(exam)

    题目描述

     Whence这个学期考了n次试,每一次都有一个0~20000之间的整数分数。Whence本来的状态应该是每一次考试都比前一次多一分(除第一次),但由于他很不稳定,偏差可能很大。对于第i次考试,如果有第j次考试满足l≤j<i≤n,且以第j次考试分数作为基准估计的第i次考试成绩比实际成绩低,就说第i次考试鄙视了第j次考试(估计分可以超过20000)。为了提高自信,Whence想知道他这个学期所有考试总共有多少次鄙视。

    输入

    第1行n (l<n≤100000);
    第2行为n次考试成绩。

    输出

    1行,这个学期所有考试的总共鄙视次数(总数可能很大,只需要输出总数mod 12345的值)。

    样例输入

    4
    1 3 3 5
    

    样例输出

    3
    

    提示

    样例说明:第一次考试的分数是1,那么估计应该是第二次为2,第三次为3,第四次为4,但第二次实际分数为3,比2大,这是1次鄙视;第四次实际分数为5,比估计的4大,这也是1次鄙视;第二次考试的分数是3,那么估计应该是第三次为4,第四次为5,实际分数分别是3和5,所以没有鄙视;第三次考试的分数为3,那么估计第四次是4,但实际为5,这又是1次鄙视。因此总鄙视次数为3次。

    分析:依题意就是找a[j]-a[i]>j-i(j>i)的对数,既是求a[j]-j>a[i]-i的对数,所以预处理a[i]=a[i]-i,再求这些正序对。

       求正序对类似于逆序对,用归并排序(树状数组)即可。

    代码:

    归并排序:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <string.h>
    #include <string>
    #include <set>
    #include <map>
    #include <vector>
    #include <queue>
    #include <stack>
    #define rep(i,n) for(int i=0;i<n;i++)
    #define rtp(i,n) for(int i=1;i<=n;i++)
    #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
    #define mod 1000000007
    #define ll long long
    #define pi acos(-1.0)
    using namespace std;
    int a[100010],b[100010];
    ll ans;
    void count(int l,int r)
    {
        int m=(l+r)/2,i=l,j=m+1,k=l;
        if(l<m)count(l,m);
        if(m+1<r)count(m+1,r);
        while(i<=m||j<=r){
            while(i<=m&&(j>r||a[i]<=a[j]))b[k++]=a[i++];
            while(j<=r&&(i>m||a[j]<a[i]))b[k++]=a[j++],ans+=m-i+1,ans%=12345;
        }
        for(i=l;i<=r;i++)a[i]=b[i];
    }
    int main()
    {
        int i,j,m,n,k;
        scanf("%d",&n);
        ans=0;
        rep(i,n)scanf("%d",&a[i]),a[i]-=i;
        reverse(a,a+n);
        count(0,n-1);
        cout<<ans<<endl;
        //system ("pause");
        return 0;
    }

    树状数组

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <list>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define Lson L, mid, rt<<1
    #define Rson mid+1, R, rt<<1|1
    const int maxn=1e5+10;
    const int dis[4][2]={{0,1},{-1,0},{0,-1},{1,0}};
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,k,t,p[maxn],a[maxn],b[maxn],num;
    ll ans;
    void add(int x,int y)
    {
        for(int i=x;i<=num;i+=(i&(-i)))
            p[i]+=y;
    }
    int get(int x)
    {
        int res=0;
        for(int i=x;i;i-=(i&(-i)))
            res+=p[i];
        return res;
    }
    int main()
    {
        int i,j;
        scanf("%d",&n);
        rep(i,0,n-1)scanf("%d",&a[i]),a[i]-=i,b[i]=a[i];
        sort(b,b+n);
        num=unique(b,b+n)-b;
        rep(i,0,n-1)a[i]=lower_bound(b,b+num,a[i])-b+1;
        rep(i,0,n-1)
        {
            add(a[i],1);
            ans+=get(a[i]-1),ans%=12345;
        }
        printf("%lld
    ",ans);
        //system("Pause");
        return 0;
    }
  • 相关阅读:
    每周学算法/读英文/知识点心得分享 1.28
    ARTS 1.21
    ARTS 1.14
    ARTS 1.7
    ARTS 12.31
    ARTS 12.24
    Leetcode : Median of Two Sorted Arrays
    我是怎样改善遗留系统的
    《大话重构》免费送书活动开始啦
    我的新书终于要出来啦
  • 原文地址:https://www.cnblogs.com/dyzll/p/5722875.html
Copyright © 2020-2023  润新知