zoukankan      html  css  js  c++  java
  • 题解 P1311 【选择客栈】

    看看大家都是\(O(n)\)的,小蒟蒻已经方得不行……

    那我来一篇\(O(nk+nlogn)\)的好了,还是可以AC哒


    \(cnt_i\)表示前i家中最低消费不超过\(p\)元的咖啡馆的数量

    \(sum_{i,k}\)表示前i家中k色调的客栈总数

    我们枚举第一家客栈

    并计算此时选择第二家客栈的方法总数

    (就是有多少家客栈符合要求,是同色调,中间有合适的咖啡馆的)


    同色调我们已经用前缀和维护了

    现在的关键是怎么找到合适的咖啡馆

    O(n)枚举显然会TLE

    但是我们快乐地发现cnt数组(合适的咖啡馆的前缀和)是递增的

    所以我们可以二分来寻找这个最靠前的合适的咖啡馆

    由于我是个又懒又容易写错二分的人

    我们使用upper_bound来寻找


    但是当你兴冲冲地写完的时候会发现过不了样例

    是不是很自闭?

    tmp_i=max(tmp_i,i+1);

    我们需要这句话,

    不然我们的答案就是错的

    会多算一个。

    如果想不明白把样例带进去就可以了


    输入+计算前缀和\(O(nk)\)

    计算方案总数\(O(nlogn)\)

    可以过

    #include <bits/stdc++.h>
    using namespace std;
    struct pos{
    	int color,cost;
    }inn[200005];
    int n,k,p,ans;
    int cnt[200005];
    //【前缀和】前i家中合适的咖啡馆的数量
    int sum[200005][55]; 
    //【前缀和】sum[i][k] 前i家中k色调的客栈总数  
    int main() {
    	scanf("%d%d%d",&n,&k,&p);
    	for(int i=1;i<=n;i++){
    		cnt[i]=cnt[i-1];
    		for(int j=0;j<=k-1;j++) sum[i][j]=sum[i-1][j]; 
    		scanf("%d%d",&inn[i].color,&inn[i].cost);
    		if(inn[i].cost<=p) cnt[i]++;
    		sum[i][inn[i].color]++;
    	} 
            //输入+计算前缀和
    	for(int i=1;i<=n;i++){
    		int tmp_i=upper_bound(cnt+1,cnt+n+1,cnt[i-1])-cnt;
    		tmp_i=max(tmp_i,i+1);
                    //寻找第一家最低消费不超过p元的咖啡馆
    		int qaq=sum[n][inn[i].color]-sum[tmp_i-1][inn[i].color];
    		if(qaq>0) ans+=qaq;//计算方法总数 
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
    qaqaq
  • 相关阅读:
    hadoop之 mr输出到hbase
    北美IT公司大致分档
    推荐系统(协同过滤,slope one)
    机器学习的常见面试问题
    关联规则之Aprior算法(购物篮分析)
    Python的Set和List的性能比较 + 两者之间的转换
    Python 集合set添加删除、交集、并集、集合操作符号
    3.算法-二叉树遍历
    1.系统设计-概要
    2算法-二分查找
  • 原文地址:https://www.cnblogs.com/zdsrs060330/p/13095104.html
Copyright © 2011-2022 走看看