首页 > 编程语言 >算法刷题532113D

算法刷题532113D

时间:2022-12-04 15:34:57浏览次数:67  
标签:532113D int ll mid high 算法 low define 刷题

题目链接

https://vjudge.net/contest/532113#problem/D

思考

虽然AC之后觉得题目难度不是很高,但也是第一次做比较综合的题目,花了快一天才做出来,只能说水平还是菜

思路

  1. 尝试直接暴力,会TLE
  2. 尝试优化
  • TLE主要瓶颈在于第二层,因此需要优化第二层的时间复杂度为\(O(logn)\),将查找\(low\)、\(high\)的代码替换为二分查找
  • 需要记录\(low-high\)之间的元素数,选择前缀和进行存储,方便查找
  • 对于重复的元素可以用unorder_ed<int,int> map进行优化

代码

#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;
const int N=200010;
ll t,n,l,r,xin;
unordered_map<ll,ll> mm;
ll a[N],p[N];
int b_search1(int low,int high,ll x){
    while (low<high)
    {
        int mid=low+high>>1;
        if(a[mid]+x>=l) high=mid;
        else low=mid+1;
    }
    return low;
}
int b_search2(int low,int high,ll x){
    while (low<high)
    {
        // cout<<low<<' '<<high<<endl;
        int mid=low+high>>1;
        if(a[mid]+x>=r) high=mid;
        else low=mid+1;
    }
    return low;
}
int main(){
    io;
    cin>>t;
    while (t--)
    {
        mm.clear();
        ll cnt=0,j=0;
        cin>>n>>l>>r;
        for (ll i = 1; i <= n; i++)
        {
            cin>>xin;
            if(!mm.count(xin)){
                a[++j]=xin;
            }
            mm[xin]++;
        }  
        sort(a+1,a+j+1);
        for (ll i = 1; i <= j; i++)
        {
            p[i]=p[i-1]+mm[a[i]];
        }  
        for (ll i = 1; i < j; i++)
        {
            if(a[i]+a[i+1]>r||a[i]+a[j]<l) continue;
            int low=b_search1(i+1,j,a[i]);
            int high=b_search2(i+1,j,a[i]);
            if(a[i]+a[high]>r) high--;
            if(a[i]+a[low]<l) low++;
	    //这里需要注意
            if(high>=low) cnt+=(p[high]-p[low-1])*mm[a[i]];
        }
	//最后对重复的元素进行判断
        for (ll i = 1; i <= j; i++)
        {
            ll cnti=mm[a[i]];
            if(cnti>=2&&2*a[i]>=l&&2*a[i]<=r){
                cnt+=(cnti*(cnti-1))/2;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

标签:532113D,int,ll,mid,high,算法,low,define,刷题
From: https://www.cnblogs.com/karson3/p/16949961.html

相关文章

  • 第一章 算法在计算中的作用
    第1章算法在计算中的作用第一周记于2022/12/4“是否存在一个通用的过程(算法)。可以自动判定任意命题是否正确?”否算法:一个定义明确的是可计算过程(Input->......
  • 初级数论1:(扩展)欧几里得算法
    初级数论第一节:欧几里得算法,扩展欧几里得算法,例题。这是你也能看懂的数论。欧几里得算法首先讲一下欧几里得算法欧几里得算法是可以在$O(\log_n)$时间内求解两数最大......
  • 算法刷题入门线性表|单调栈
     一、概念1、栈的定义栈 是仅限在 一端 进行 插入 和 删除 的 线性表。 栈 又被称为后进先出(LastInFirstOut)的线性表,简称LIFO。2、栈顶栈 是一......
  • 每日算法之栈的压入、弹出序列
    JZ31栈的压入、弹出序列描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,......
  • 【CV算法理解与源码实现】DeepSORT
    前言 论文:​​SimpleOnlineandRealtimeTrackingwithaDeepAssociationMetric​​ 参考1.​​deepsort_github​​;2.​​deepsort_paper​​;3. ​​ComputerVi......
  • Delayed ACK与Nagle算法相互作用
    DelayedACK​​DelayedACK​​是TCP的一种流控手段。如果有响应数据发送时,ACK会随响应数据一起发送给对方;如果没有响应数据,ACK的发送就会有延迟,以等待看是否有响应数......
  • 动态分区分配算法
    一、首次适应算法(FirstFit)算法思想每次都从低地址开始查找,找到第一个能满足大小的空闲分区。空闲分区以地址递增的次序排列。每次分配内存时顺序查找空闲分区链(......
  • 常见算法
    1//算法2//设计将两个递增有序带头结点链表合并为一个有序递减的链表。3//1,2,3,4,54//2,5,9,105voidMergeList(LinkList&La,LinkList&Lb)6{......
  • 算法图解笔记
    前言知识第一章,算法简介1.2,二分法查找元素1.2.1,特殊的二分查找第二章,选择排序2.1,内存工作原理2.2.1,链表2.2.2,数组2.2.3,术语2.3,选择排序2.4,小结第......
  • LeetCode刷题记录.Day30
    二叉树的前序遍历递归遍历法classSolution{public:voidtraversal(TreeNode*cur,vector<int>&result){if(cur==NULL)return;//当前节点为空,终......