• [CSP-S模拟测试]:购物(柯朵莉树)


    题目描述

    $visit_world$有一个商店,商店里卖$N$个商品,第$i$个的价格为$a[i]$我们称一个正整数$K$是美妙的,当且仅当我们可以在商店里选购若干个商品,使得价格之和落在区间$[K,2K]$中。
    问:有多少个美妙的数。


    输入格式

    第一行一个整数$N$。
    接下来一行$N$个整数,描述数组$a[]$。


    输出格式

    输出一行一个整数,表示答案。


    样例

    样例输入:

    3
    1 2 3

    样例输出:

    6


    数据范围与提示

    样例解释:

    可以证明$1leqslant Kleqslant 6$都是美妙的,除此之外的数都不是美妙的。

    数据范围:

    子任务$1$($30$分):$Nleqslant 100,a_ileqslant 100$。
    子任务$2$($20$分):$Nleqslant 100000,a_ileqslant 20$。
    子任务$3$($20$分):$Nleqslant 3,a_ileqslant 10^9$。
    子任务$4$($30$分):$Nleqslant 10^5,a_ileqslant 10^9$。


    题解

    正解不会,今天刚学柯朵莉树,于是就打了它(可惜考试的时候并不会……)

    基本上就是一道柯朵莉树的板子题,不妨就拿它来讲一下柯朵莉树吧~

    柯朵莉树的原理很简单,就是不断往里面添加区间,添加完之后再进行合并(有交集的两个区间合并),用$set$维护这些区间就好了。

    来讲几个细节:

      $alpha.$添加区间的时候,如果要同时添加多个区间(比如这道题),需要先枚举$set$里所有的原区间,生成新的区间并将这些区间放到$vector$里,如果直接放进去会造成死循环(当然也是错的)。

      $eta.$合并时与前一个区间比较,会更方便处理(细节看代码)。

      $gamma.$合并之后注意$it$指针的位置,可以用二分查找……

    时间复杂度:$Theta(nloglog n)$(随机数据)。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int N;
    int a[100001];
    set<pair<int,long long>>s;
    vector<pair<int,long long>>v;
    long long ans;
    void add(int x)
    {
    	for(auto it=s.begin();it!=s.end();it++)
    		v.push_back(make_pair((*it).first+x,(*it).second+2*x));
    	while(v.size())
    	{
    		s.insert(v.back());
    		v.pop_back();
    	}
    }
    void split()
    {
    	for(auto it=s.begin();;)
    	{
    		auto ti=it;it++;
    		if(it==s.end())break;
    		if((*ti).second>=(*it).first)
    		{
    			pair<int,long long> flag=make_pair((*ti).first,(*it).second);
    			s.erase(it);s.erase(ti);s.insert(flag);
    			it=s.lower_bound(flag);
    		}
    	}
    }
    int main()
    {
    	scanf("%d",&N);
    	s.insert(make_pair(0,0));
    	for(int i=1;i<=N;i++)
    	{
    		scanf("%d",&a[i]);
    		add(a[i]);
    		split();
    	}
    	for(auto it=s.begin();it!=s.end();it++)
    	{
    		if(!(*it).first)continue;
    		ans+=((*it).second+1)/2-((*it).first-1)/2;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    百度首页暗藏的2019招聘广告彩蛋,非技术人员很难发现,看来是定向发送啊
    ipv6地址在URL中的表达方式,如何在URL地址中包含ipv6地址
    只用ipv6 两台机器共享文件夹, 局域网连接路径,共享文件夹路径中ipv6地址如何表示
    iconfont图标symbol引用方式,有的图标不能通过设置color样式来修改颜色的解决办法
    shell脚本面试题
    常用的Shell脚本
    JAVA面试题
    Linux系统基础优化
    Linux磁盘设备基础
    Linux系统的目录结构及常见目录总结
  • 原文地址:https://www.cnblogs.com/wzc521/p/11689836.html
Copyright © 2020-2023  润新知