首页 > 其他分享 >离散化和区间合并一

离散化和区间合并一

时间:2023-03-15 21:57:34浏览次数:45  
标签:int ed 合并 st 离散 second alls 区间

离散化

  • 一个序列长度非常大(>10^5 一般10^9左右),但是有值的元素却十分稀疏

    image-20230315133016375

  • 这里使用离散化映射+前缀和处理
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 3e5+10;
int n,m;
//a[i] 存储的是插入下标位i的值
//s[i] 为a的前缀和
int a[N],s[N];
//存储所有需要离散化元素的下标(想一下包括题目中插入的下标x和询问的下标l和r)
vector<int>alls;
//存储插入和询问操作数据
vector<pair<int,int>> add,query;
//法一 二分查找的写法,哪里错了呢
// int find(int x){
//     int l=0,r=alls.size()-1;
//     while(l<=r){
//         int mid=(l+r)>>1;
//         if(x<a[mid]) r=mid-1;
//         else if(x>a[mid]) l=mid+1;
//         else{
//             //映射为 1,2....n
//             return mid+1;
//         }
//     }
//     return -1;
// }
//法二 二分写法(二分要强于二分查找,二分查找仅适用于元素个数为1的时候)
int find(int x){
    int l=0,r=alls.size()-1;
    while(l<r){
        int mid=l+r>>1;
        if(alls[mid]>=x) r=mid;
        else l=mid+1;
    }
    return r+1;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int x,c;
        cin>>x>>c;
        add.push_back({x,c});
        alls.push_back(x);
    }
    for(int i=1;i<=m;i++){
        int l,r;
        cin>>l>>r;
        query.push_back({l,r});
        alls.push_back(l);
        alls.push_back(r);
    }
    // alls 排序+去重
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());
    //初始化a[x]中有被插入的部分
    for(auto item :add){
        //通过假想的下标找到在a数组中对应的下标
        int x=find(item.first);
        a[x]+=item.second;
    }
    //前缀和
    for(int i=1;i<=alls.size();i++){
        s[i]=s[i-1]+a[i];
    }
    for(auto item:query){
        int l=find(item.first);
        int r=find(item.second);
        cout<<s[r]-s[l-1]<<endl;
    }
    return 0;
}
  • 区间合并

    image-20230315213745763

    • 区间合并,一般是对所有区间按照左(右)端点排序,然后维护一个中间变量区间(一般用第一个区间初试)[st,ed],然后后边的每一个区间和这个区间比较如果后面的这个区间的左端点<=变量区间的ed,那么说明他们有交集,那么变量区间的ed=max(ed,后一个区间.右端点),否则没有交集那么直接将现在的[st,ed]存入用于保存最后剩余区间的vector<pair<int,int>>中; 然后st=后一个区间.起点,ed=后一个区间;最后的那个区间是没法和后面比的,也要直接存入vector中
    • //法一,只算剩余区间个数
      // #include<iostream>
      // #include<algorithm>
      // using namespace std;
      // typedef pair<int,int> PII;
      // const int N = 1e5+10;
      // int n;
      // PII a[N];
      // int main()
      // {
      //     cin>>n;
      //     for(int i=1;i<=n;i++){
      //         cin>>a[i].first>>a[i].second;
      //     }
      //     sort(a+1,a+n+1);
      //     //区间合并类问题,我们会维护一个区间 [st,ed]
      //     int ed=a[1].second,ans=1;
      //     for(int i=2;i<=n;i++){
      //         //新的区间和我们维护的区间有交集
      //         if(ed>=a[i].first) ed=max(ed,a[i].second);
      //         //新添加和区间和我们维护的区间没有交集,ans++,维护这个新添加的区间
      //         else ans++,ed=a[i].second;
      //     }
      //     cout<<ans<<endl;
      //     return 0;
      // }
      //法二,算区间个数 并维护合并后的区间情况
      #include<iostream>
      #include<algorithm>
      using namespace std;
      typedef pair<int,int> PII;
      const int N = 1e5+10;
      int n;
      PII a[N];
      vector<PII> res;
      int main(){
          cin>>n;
          for(int i=1;i<=n;i++){
              cin>>a[i].first>>a[i].second;
          }
          sort(a+1,a+n+1);
          int st=a[1].first,ed=a[1].second,ans=1;
          for(int i=2;i<=n;i++){
              if(ed>=a[i].first) ed=max(ed,a[i].second);
              else{
                  res.push_back({st,ed});
                  ans++;
                  st=a[i].first,ed=a[i].second;
              }
          }
          //最后一个[st,ed]的区间,也要合并到res;
          res.push_back({st,ed});
      ​
          cout<<ans<<endl;
          // for(auto t:res){
          //     cout<<t.first<<" "<<t.second<<endl;
          // }
          return 0;
      }

标签:int,ed,合并,st,离散,second,alls,区间
From: https://www.cnblogs.com/zhouylove/p/17220239.html

相关文章

  • 020:闭区间上连续函数性质之零点定理、介值定理
    020:闭区间上连续函数性质之零点定理、介值定理......
  • 二分查找——区间开闭性
    具体到代码上,二分查找时区间的左右端取开区间还是闭区间在绝大多数时候都可以,因此有些初学者会容易搞不清楚如何定义区间开闭性。这里我提供两个小诀窍,第一是尝试熟练使用......
  • 【C#】pdf文件合并
    环境:VS2019+Win10+.NETFramework3.5依赖于:itextsharp.dll 源码,封装接口:///<summary>///合并pdf文件至输出文件///</summary>......
  • 表格单元格合并
    表格单元格合并 单元格合并属性水平合并:colspan垂直合并:rowspan<tableborder="1"width=500pxheight="500px">  <tr>    <td>单元1</td>   ......
  • 线段树分裂合并
    概述线段树分裂这里暂时没有。线段树合并是指将管辖范围相同的两棵线段树对位(节点意义下)合并。线段树合并线段树合并支持各种统计子树的操作。详细来讲就是,......
  • 查询学生考试得分区间人数,根据"10-20","20-30","30-40","40-50","50-60&q
    selectelt(interval(get_point,10,20,30,40,50,60,70,80,90),"10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90","90-100")asscore_level,count(*)as......
  • 【CF1572C Paint】(区间dp)
    原题链接题意给定长度为\(n\)的颜色序列\(a_i\),每次你可以选择任意长度的连续且颜色相同的一段位置,将其全部变成任意同一种颜色,问你最少总共需要多少次操作才能使得整......
  • 离散数学——图论
    设\(A,B\)为任意的两个集合,称\[\{\{a,b\}\mida\inA\wedgeb\inB\}\]为\(A\)与\(B\)的无序积,记作\(A\&B\).为方便起见,将无序积中的无序对\(\{a,......
  • 力扣简21 合并两个有序链表
    递归特别短!没这种思维!  自己用那种最直白的两个两个相比换指针指向导致会有空情况等特殊情况出错 看了题解是用递归什么的扩展一下这种思路而且可以采用给链表加......
  • mysql elt interval函数区间统计
    引言 在实际的业务统计需求中有时往往需要对区间进行分组统计查询,如分数区间,工资区间查询统计等!mysql中可以利用elt函数来实现此类需求!接下来看如下时间业务需求:......