1. 程式人生 > >hdu 6119 小小粉絲度度熊(區間雙指針)

hdu 6119 小小粉絲度度熊(區間雙指針)

memset nbsp 題目 while php pan src amp ret

題目鏈接:hdu 6119 小小粉絲度度熊

題意:

給你n個區間,和一個數m,m表示可補上不連續的位置累計和為m,現在問你最長的連續區間和為多少。

題解:

我可能寫的有點復雜,大概就是將每個區間排序後離散化,將這些間隔看成一個點,然後雙指針一下。

技術分享
 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 typedef pair<int,int>P;
6 7 const int N=1e5+7; 8 int n,m,hsh[N*3],ed,cnt[N*4],ced,C[N*4]; 9 int IS[N*4]; 10 P seg[N]; 11 12 void add(int x,int v){while(x<=ced)C[x]+=v,x+=x&-x;} 13 int ask(int x){int an=0;while(x)an+=C[x],x-=x&-x;return an;} 14 15 void solve() 16 { 17 int ans=0,cha=m,sum=0; 18 for(int l=1
,r=1;r<=ced;r++) 19 { 20 int is=IS[r]; 21 if(is)sum+=cnt[r]; 22 else cha-=cnt[r],sum+=cnt[r]; 23 while(l<=r&&cha<0) 24 { 25 int is=IS[l]; 26 if(is)sum-=cnt[l]; 27 else cha+=cnt[l],sum-=cnt[l]; 28 l++;
29 } 30 ans=max(ans,sum+cha); 31 } 32 printf("%d\n",ans); 33 } 34 35 int main(){ 36 while(~scanf("%d%d",&n,&m)) 37 { 38 ced=0;mst(C,0);mst(IS,0); 39 ed=0;hsh[++ed]=0;hsh[++ed]=(int)(1e9+7); 40 F(i,1,n) 41 { 42 scanf("%d%d",&seg[i].first,&seg[i].second); 43 seg[i].first++,seg[i].second++; 44 hsh[++ed]=seg[i].first,hsh[++ed]=seg[i].second; 45 } 46 sort(hsh+1,hsh+1+ed),ed=unique(hsh+1,hsh+1+ed)-hsh-1; 47 F(i,2,ed) 48 { 49 cnt[++ced]=hsh[i]-hsh[i-1]-1; 50 cnt[++ced]=1; 51 } 52 F(i,1,n) 53 { 54 int idx=lower_bound(hsh+1,hsh+1+ed,seg[i].first)-hsh; 55 idx=(idx-1)*2; 56 add(idx,1); 57 idx=lower_bound(hsh+1,hsh+1+ed,seg[i].second)-hsh; 58 idx=(idx-1)*2; 59 add(idx+1,-1); 60 } 61 F(i,1,ced)IS[i]=ask(i); 62 solve(); 63 } 64 return 0; 65 }
View Code

hdu 6119 小小粉絲度度熊(區間雙指針)