1. 程式人生 > >整體二分初識--POJ2104:K-th Number

整體二分初識--POJ2104:K-th Number

只需要 區域 左右 gif max 技術 因此 space efi

n<=100000個數有m<=5000個詢問,每次問區間第k大。

方法一:主席樹!……

方法二:整體二分。

整體二分一次性計算半個值域對一個區間的詢問的貢獻,然後根據“這半邊的貢獻在某個詢問中可不可以直接處理掉”把詢問分兩部分,並按“數字的值是否在這半邊”把數字也分成兩部分,這樣把一個區間和值域都分掉了,然後就可以在f(n)logMax的時間出解,其中f(n)表示計算一次這樣的貢獻需要的時間。

在這題裏,只需要看某個區間裏在值域[L,mid]中出現的數字的個數有沒有到K個,以此劃分成兩個區域。因此樹狀數組搞一搞,f(n)=nlogn,大功告成。

技術分享圖片
 1 //#include<iostream>
2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<bitset> 6 #include<algorithm> 7 //#include<cmath> 8 using namespace std; 9 10 int n,m; 11 #define maxn 200011 12 const int inf=0x3f3f3f3f; 13 struct App 14 { 15 int x,y,z,id,type; 16 //
type=1 表示修改,其中x為位置,y為數值,z為在bit中的修改權值 17 //type=0 表示詢問,其中x,y為左右端點,z是第幾大,id詢問編號 18 }a[maxn],al[maxn],ar[maxn]; 19 int ans[maxn]; 20 21 struct BIT 22 { 23 int a[maxn]; 24 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 25 int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return
ans;} 26 }t; 27 28 void solve(int L,int R,int ql,int qr) 29 { 30 if (ql>qr || L>R) return; 31 if (L==R) 32 { 33 for (int i=ql;i<=qr;i++) ans[a[i].id]=L; 34 return; 35 } 36 const int mid=(L+R)>>1; 37 int lal=0,lar=0; 38 for (int i=ql;i<=qr;i++) 39 { 40 if (a[i].type) 41 { 42 if (a[i].y<=mid) 43 { 44 t.add(a[i].x,a[i].z); 45 al[++lal]=a[i]; 46 } 47 else ar[++lar]=a[i]; 48 } 49 else 50 { 51 int tmp=t.query(a[i].y)-t.query(a[i].x-1); 52 if (tmp>=a[i].z) al[++lal]=a[i]; 53 else 54 { 55 ar[++lar]=a[i]; 56 ar[lar].z-=tmp; 57 } 58 } 59 } 60 for (int i=1;i<=lal;i++) if (al[i].type==1) t.add(al[i].x,-al[i].z); 61 for (int i=1,j=ql;i<=lal;i++,j++) a[j]=al[i]; 62 for (int i=1,j=ql+lal;i<=lar;i++,j++) a[j]=ar[i]; 63 solve(L,mid,ql,ql+lal-1); 64 solve(mid+1,R,ql+lal,qr); 65 } 66 67 int main() 68 { 69 scanf("%d%d",&n,&m); 70 for (int i=1;i<=n;i++) scanf("%d",&a[i].y),a[i].x=i,a[i].z=1,a[i].type=1; 71 for (int i=1,j=n+1;i<=m;i++,j++) scanf("%d%d%d",&a[j].x,&a[j].y,&a[j].z),a[j].id=i,a[j].type=0; 72 solve(-inf,inf,1,n+m); 73 for (int i=1;i<=m;i++) printf("%d\n",ans[i]); 74 return 0; 75 }
View Code

整體二分初識--POJ2104:K-th Number