【二分+尺取】HDU 6119 小小粉丝度度熊

http://acm.hdu.edu.cn/showproblem.php?pid=6119

【思路】

  • 首先通过处理交叉的可以处理成不交叉的
  • 然后二分查找答案
  • 如何判断一个长度是否可行?
  • 双指针O(n)扫一次就可以,要处理区间和问题,所以先求前缀和
  • 时间复杂度O(nlogn)

【AC】

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<algorithm>
  6 #include<cmath>
  7 
  8 using namespace std;
  9 typedef long long ll;
 10 const int maxn=1e5+3;
 11 int n,m;
 12 int cnt1,cnt2;
 13 struct node
 14 {
 15     int l;
 16     int r;
 17 }a[maxn];
 18 int b[maxn];
 19 int c[maxn];
 20 int pre1[maxn];
 21 int pre2[maxn];
 22 
 23 bool cmp(node x,node y)
 24 {
 25     if(x.l!=y.l) return x.l<y.l;
 26     return x.r<y.r;
 27 }
 28 void Pre()
 29 {
 30     memset(pre1,0,sizeof(pre1));
 31     pre1[0]=b[0];
 32     for(int i=1;i<cnt1;i++)
 33     {
 34         pre1[i]=pre1[i-1]+b[i];
 35     }
 36     memset(pre2,0,sizeof(pre2));
 37     pre2[0]=c[0];
 38     for(int i=1;i<cnt2;i++)
 39     {
 40         pre2[i]=pre2[i-1]+c[i];
 41     }
 42     
 43 }
 44 bool check(int p,int q,int mid)
 45 {
 46     if(p==0) return pre1[q]>=mid;
 47     return pre1[q]-pre1[p-1]>=mid;
 48 }
 49 bool judge(int mid)
 50 {
 51     int pos=upper_bound(pre2,pre2+cnt2,m)-pre2-1;
 52     int totm=pre2[pos];
 53     int p=0,q=pos+1;
 54     while(p<=q&&q<cnt1)
 55     {
 56         if(check(p,q,mid))
 57         {
 58             return true;
 59         }
 60         else
 61         {
 62             totm-=c[p];
 63             p++;
 64             while(pos+1<cnt2&&totm+c[pos+1]<=m)
 65             {
 66                 totm+=c[pos+1];
 67                 pos++;
 68             }
 69             q=pos+1;
 70         }
 71     }
 72     return false;
 73 }
 74 int main()
 75 {
 76     while(scanf("%d%d",&n,&m)!=EOF)
 77     {
 78         for(int i=0;i<n;i++)
 79         {
 80             scanf("%d%d",&a[i].l,&a[i].r);
 81         }
 82         sort(a,a+n,cmp);
 83         cnt1=0;
 84         cnt2=0;
 85         int p=a[0].l,q=a[0].r;
 86         int low=0,high=0;
 87         for(int i=1;i<n;i++)
 88         {
 89             if(a[i].l<=q)
 90             {
 91                 q=max(q,a[i].r);
 92             }
 93             else
 94             {
 95                 b[cnt1++]=q-p+1;
 96                 high+=q-p+1;
 97                 c[cnt2++]=a[i].l-q-1;
 98                 p=a[i].l;
 99                 q=a[i].r;
100             }
101         }
102         b[cnt1++]=q-p+1;
103         high+=q-p+1;
104         Pre();
105         while(low<=high)
106         {
107             int mid=(low+high)>>1;
108             if(judge(mid))
109             {
110                 low=mid+1;
111             }
112             else
113             {
114                 high=mid-1;
115             }
116         }
117         cout<<low+m-1<<endl;
118     }
119     return 0;
120 }
View Code
原文地址:https://www.cnblogs.com/itcsl/p/7354318.html