zoukankan      html  css  js  c++  java
  • meizi

    [l,r]有一条线段,a[l],a[l+1]......,a[r]全部加一,求max{a[i]}......

    所以可以用前缀和差分,[l,r]有一条线段,b[l]++,b[r]--,ans=max{sum[i]}......

    因为l,r比较大,所以要离散化......

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n;
     6 int tmp[4000005], a[2000005], b[2000005], s[4000005];
     7 int main(){
     8     
     9     int n;
    10     scanf("%d", &n);
    11     for(int i = 1; i <= n; i ++){
    12         scanf("%d%d", &a[i], &b[i]);
    13         tmp[2 * i - 1] = a[i]; tmp[2 * i] = b[i];
    14     }
    15     sort(tmp + 1, tmp + 2 * n + 1);
    16     for(int i = 1; i <= n; i ++){
    17         a[i] = lower_bound(tmp + 1, tmp + 2 * n + 1, a[i]) - tmp;
    18         b[i] = lower_bound(tmp + 1, tmp + 2 * n + 1, b[i]) - tmp;
    19         s[a[i]] ++; s[b[i] + 1] --;
    20     }
    21     for(int i = 1; i <= 2 * n; i ++) s[i] += s[i - 1];
    22     int ans = 0;
    23     for(int i = 1; i <= 2 * n; i ++) ans = max(ans, s[i]);
    24     printf("%d
    ", ans);
    25     
    26     return 0;
    27 } 

     也可以用枚举,然后不断算的方法

    一开始想的是按右端点排序,从前往后做,把算过的线段的右端点记录,每次排序,然后用lower_bound查找可以连接上的最靠后的右端点,最差的,复杂度是O(n^2logn)......

    所以要寻找一种有单调性的方式......

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn=2e5+7;
     7 int n,size,ans=1,head=1;
     8 int rr[maxn];
     9 struct Node{
    10     int l,r;
    11 }node[maxn];
    12 bool cmp(Node a,Node b){
    13     return a.r<b.r;
    14 }
    15 int main(){
    16     cin>>n;
    17     for(int i=1;i<=n;i++) cin>>node[i].l>>node[i].r;
    18     sort(node+1,node+n+1,cmp);
    19     rr[ans]=node[1].r;
    20     for(int i=2;i<=n;i++){
    21         int t=ans;
    22         t=lower_bound(rr+1,rr+ans+1,node[i].l)-rr-1;
    23         if(t==0){
    24             ans++;rr[ans]=node[i].r;
    25         }
    26         else{
    27             rr[t]=node[i].r;
    28             sort(rr+1,rr+ans+1);
    29         }
    30     } 
    31     cout<<ans<<endl;
    32     return 0;
    33 } 

    采用以左端点排序,从左向右做,因为左端点有单调性,肯定变得越来越优,所以可以将已经计算过的线段的右端点加入一个堆中,每次弹出最小的,即最优的点,不行的话就加一个杯子

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=2e5+7;
     8 int n,size,ans=1,head=1;
     9 int rr[maxn];
    10 priority_queue<int,vector<int>,greater<int>>q;
    11 struct Node{
    12     int l,r;
    13 }node[maxn];
    14 bool cmp(Node a,Node b){
    15     return a.l<b.l;
    16 }
    17 int main(){
    18     cin>>n;
    19     for(int i=1;i<=n;i++) cin>>node[i].l>>node[i].r;
    20     sort(node+1,node+n+1,cmp);
    21     q.push(node[1].r);
    22     for(int i=2;i<=n;i++){
    23         int ri=q.top();
    24         if(node[i].l<=ri){
    25             ans++;q.push(node[i].r);
    26         } 
    27         else{
    28             q.pop();q.push(node[i].r);
    29         }
    30     }
    31     cout<<ans<<endl;
    32     return 0;
    33 } 

    lower_bound是大于等于这个值

    upper_bound是大于这个值

  • 相关阅读:
    Linux基础篇之软件源码包安装
    11-1 网络协议和管理
    bash-2 httpd服务的源码编译安装脚本
    8-1 文本三级剑客之sed
    9-3 磁盘存储与分区
    9-2 yum,dnf和apt
    9-1 软件包管理
    bash-1 初始化CentOS系统的初始化脚本
    3-3 man手册介绍
    5-3 文件权限
  • 原文地址:https://www.cnblogs.com/lcan/p/9537887.html
Copyright © 2011-2022 走看看