2 条题解

  • 0
    @ 2026-4-23 10:55:04

    • 0
      @ 2025-10-8 17:11:11

      C34 线段树+双指针 P1712 [NOI2016] 区间

      // 线段树+双指针+离散化
      #include <cstdio>
      #include <iostream>
      #include <algorithm>
      using namespace std;
      
      #define ls u<<1
      #define rs u<<1|1
      const int N=500005;
      int n,m;
      struct line{
        int l,r,len;
        bool operator<(line &b){
          return len<b.len;
        }
      }L[N];      //区间
      int X[N*2]; //X坐标
      struct tree{
        int l,r,cnt,lazy;//重叠数,懒标记
      }t[N*2*4];  //线段树
      
      void pushup(int u){   //上传
        t[ u ].cnt=max(t[ls].cnt,t[rs].cnt);
      }
      void pushdown(int u){ //下传
        if(t[ u ].lazy){
          t[ls].cnt+=t[ u ].lazy;
          t[rs].cnt+=t[ u ].lazy;
          t[ls].lazy+=t[ u ].lazy;
          t[rs].lazy+=t[ u ].lazy;
          t[ u ].lazy=0;
        }
      }
      void build(int u,int l,int r){ //建树
        t[ u ]={l,r};
        if(l==r) return;
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
      }
      void change(int u,int l,int r,int k){
        if(l>t[ u ].r||t[ u ].l>r) return;
        if(l<=t[ u ].l && t[ u ].r<=r){
          t[ u ].cnt+=k;
          t[ u ].lazy+=k;
          return;
        }
        pushdown(u);
        change(ls,l,r,k);
        change(rs,l,r,k);
        pushup(u);
      }
      int main(){
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++){
          int a,b; scanf("%d%d",&a,&b);
          X[i]=a; X[i+n]=b;
          L[i]={a,b,b-a};
        }
        sort(L+1,L+n+1);  //按长度排序
        sort(X+1,X+n*2+2);              //排序
        int k=unique(X+1,X+n*2+1)-X-1;  //去重
        for(int i=1; i<=n; i++){        //离散化
          L[i].l=lower_bound(X+1,X+k+1,L[i].l)-X;
          L[i].r=lower_bound(X+1,X+k+1,L[i].r)-X;
        }
        build(1,1,k); //k最大是2*n
        int ans=1e9;
        for(int i=0,j=0; j<=n;){    //双指针
          while(t[1].cnt<m && j<=n)
            j++, change(1,L[j].l,L[j].r,1);
          if(t[1].cnt<m) break;     //无解
          while(t[1].cnt==m && i<=j)
            i++, change(1,L[i].l,L[i].r,-1);
          ans=min(ans,L[j].len-L[i].len);
        }
        printf("%d",ans==1e9?-1:ans);
      }
      
      • 1

      C34 线段树+双指针 [NOI2016] 区间

      信息

      ID
      6318
      时间
      3000ms
      内存
      256MiB
      难度
      8
      标签
      递交数
      99
      已通过
      15
      上传者