1 条题解

  • 0
    @ 2026-6-2 23:48:11

    注意到

    本题两种做法

    题意: 每个数得分 = 它左边比它小的数的数量找到最大得分,≥k 输出 Yes,否则 No。

    1:树状数组

    从左逐个遍历数组;

    查询 1~a[i]-1 已有多少数 → 当前得分;

    把 a [i] 加入树状数组;

    全程记录最大得分,最后判断。

    复杂度:O (nlogn)

    2:归并分治

    (上机培训让你求了逆序对个数,这次其实是正序对)

    数组不断分成左右两段,左段全都在右段左边;

    合并有序数组时,统计左小于右的数量,累加进得分;

    递归算出所有得分,取最大值判断。

    复杂度:O (nlogn)

    证明如下

    1. 暴力算法不可行证明 总统计次数:T = 0+1+2+...+(n-1) = n*(n-1)/2,时间复杂度 O (n²)

    代入 n=5*10 的 5 次方,运算总量约 1.25 乘 10 的 11 次方次。

    电脑一秒最多运行 10 的 8 次方次运算,计算耗时远大于题目 1~2 秒时限,暴力超时不能用。

    2. 树状数组解法

    cnt [x]=1 代表数字 x 之前出现过

    每个元素得分 = 1 到 a [i]-1 所有已出现数字总数 = 查询 (a [i]-1)

    顺序遍历:先查得分,再把当前数字标记存入,计算逻辑和题目定义完全一致。

    复杂度 单次查询、修改耗时 log n,n 个数字总复杂度 O (n log n)

    3. 归并排序解法

    区间分成左 [l,mid]、右 [mid+1,r],左边所有数在原数组都排在右边数前面。

    合并有序数组时统计左边小于右边的数字个数,递归结束得到全部得分。

    复杂度 递归层数 log n,每层一共遍历 n 个数据,总复杂度 O (n log n)

    C++树状数组解法

    
    const int N=5e5+5;
    int tr[N];
    void add(int x)
    {
    	for(;x<N;x+=x&-x)
    	tr[x]++;
    }
    
    int qry(int x)
    {
    	int s=0;
    	for(;x;x-=x&-x)
    	s+=tr[x];
    	return s;
    }
    int main()
    {
        AC;
        int n,k;
    	cin>>n>>k;
    	int ok=0;
    	for(int i=1;i<=n;i++)
    	{
    		int x;
    		cin>>x;
    		int s=qry(x-1);
    		if(s>=k)
    		ok=1;
    		add(x);
    	}
    	cout<<(ok?"Yes":"No");
        return 0;
    }
    
    

    Python 树状数组解法

    import sys
    def main():
        data=sys.stdin.read().split()
        n=int(data[0])
        k=int(data[1])
        size=500005
        tree=[0]*size
        def add(x):
            while x<size:
                tree[x]+=1
                x+=x&-x
        def query(x):
            sum=0
            while x>0:
                sum+=tree[x]
                x-=x&-x
            return sum
        ok=0
        idx=2
        for _ in range(n):
            x=int(data[idx])
            idx+=1
            res=query(x-1)
            if res>=k:
                ok=1
            add(x)
        print("Yes"if ok else"No")
    main()
    
    

    C++ 归并排序解法

    const int N=500005;
    pair<int,int> arr[N];
    int cnt[N];
    int n,k;
    bool merge_sort(int l,int r)
    {
        if(l>=r) return false;
        int mid=(l+r)/2;
        if(merge_sort(l,mid)) return true;
        if(merge_sort(mid+1,r))  return true;
        int i=l;
        for(int j=mid+1;j<=r;j++)
        {
            while(i<=mid && arr[i].first<arr[j].first)  i++;
            cnt[arr[j].second]+=i-l;
            if(cnt[arr[j].second]>=k)  return true;
        }
        vector<pair<int,int>> tmp;
        i=l;
        int j=mid+1;
        while(i<=mid && j<=r)
        {
            if(arr[i].first<=arr[j].first)
            {
                tmp.push_back(arr[i]);
                i++;
            }
            else
            {
                tmp.push_back(arr[j]);
                j++;
            }
        }
        while(i<=mid)
        {
            tmp.push_back(arr[i]);
            i++;
        }
        while(j<=r)
        {
            tmp.push_back(arr[j]);
            j++;
        }
        for(int p=l;p<=r;p++) arr[p]=tmp[p-l];
        return false;
    }
    int main()
    {
        AC;
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            cin>>arr[i].first;
            arr[i].second=i;
        }
        if(merge_sort(1,n)) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
        return 0;
    }
    

    Python 归并排序解法

    
    import sys
    def main():
        data=sys.stdin.read().split()
        n=int(data[0])
        k=int(data[1])
        a=list(map(int,data[2:2+n]))
        arr=[(a[i],i) for i in range(n)]
        cnt=[0]*n
        def merge_sort(l,r):
            if l>=r:
                return False
            mid=(l+r)//2
            if merge_sort(l,mid):
                return True
            if merge_sort(mid+1,r):
                return True
            i=l
            for j in range(mid+1,r+1):
                while i<=mid and arr[i][0]<arr[j][0]:
                    i+=1
                cnt[arr[j][1]]+=i-l
                if cnt[arr[j][1]]>=k:
                    return True
            temp=[]
            i=l
            j=mid+1
            while i<=mid and j<=r:
                if arr[i][0]<=arr[j][0]:
                    temp.append(arr[i])
                    i+=1
                else:
                    temp.append(arr[j])
                    j+=1
            temp+=arr[i:mid+1]
            temp+=arr[j:r+1]
            arr[l:r+1]=temp
            return False
        print("Yes"if merge_sort(0,n-1)else"No")
    main()
    
    
    • 1

    信息

    ID
    1162
    时间
    2000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    9
    已通过
    1
    上传者