LeetCode 刷題c++--1551. 使陣列中所有元素相等的最小運算元
阿新 • • 發佈:2020-08-17
這裡只說一下離散化的簡單思路(還不會難的(T _ T))
離散化的就是將大範圍的縮小到小範圍來表示,這類問題一般是數的範圍很大,但是個數不多,
具體的思路是,將他們用一個數組來表示,查詢其原位置時用二分查詢即可。
一個模板題:區間和
假定有一個無限長的數軸,數軸上每個座標上的數都是0。
現在,我們首先進行 n 次操作,每次操作將某一位置x上的數加c。
接下來,進行 m 次詢問,每個詢問包含兩個整數l和r,你需要求出在區間[l, r]之間的所有數的和。
輸入格式
第一行包含兩個整數n和m。
接下來 n 行,每行包含兩個整數x和c。
再接下里 m 行,每行包含兩個整數l和r。
輸出格式
共m行,每行輸出一個詢問中所求的區間內數字和。
資料範圍
−10^9≤x≤10^9 −10^9≤x≤10^9,
1≤n,m≤10^5 1≤n,m≤10^5,
−10^9≤l≤r≤10^9 −10^9≤l≤r≤10^9,
−10000≤c≤10000 −10000≤c≤10000
輸入樣例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
輸出樣例:
8
0
5
分析:數的範圍很大,但是個數卻不多,可以用一個數組來存。
程式碼如下:
1 #include<cstdio> 2 #include<algorithm> 3using namespace std; 4 const int N=3e5+10; 5 int n,m,q[N]; 6 struct node{ 7 int id,x; 8 }s[N],e[N]; 9 bool cmp(node a,node b) 10 { 11 return a.id<b.id; 12 } 13 int er1(int x)//二分查左端點 14 { 15 int l=1,r=n+2*m,mid; 16 while(l<r) 17 { 18 mid=l+r>>1; 19 if(s[mid].id>=x) 20 r=mid; 21 else 22 l=mid+1; 23 } 24 return l; 25 } 26 int er2(int x)//二分查右端點 27 { 28 int l=1,r=n+2*m,mid; 29 while(l<r) 30 { 31 mid=l+r+1>>1; 32 if(s[mid].id<=x) 33 l=mid; 34 else 35 r=mid-1; 36 } 37 return l; 38 } 39 int main() 40 { 41 int k=0; 42 scanf("%d%d",&n,&m); 43 for(int i=1;i<=n;i++) scanf("%d%d",&s[i].id,&s[i].x); 44 for(int i=n+1;i<=n+2*m;i++) 45 { 46 int l,r; 47 scanf("%d%d",&l,&r); 48 s[i].id=l;s[i].x=0; 49 i++; 50 s[i].id=r;s[i].x=0; 51 e[k].id=l;e[k].x=r; 52 k++; 53 } 54 sort(s+1,s+n+2*m+1,cmp); 55 for(int i=1;i<=n+2*m;i++) q[i]=q[i-1]+s[i].x; 56 for(int i=0;i<k;i++) 57 { 58 //printf("%d %d\n",e[i].id,e[i].x); 59 int l=er1(e[i].id); 60 int r=er2(e[i].x); 61 //printf("%d %d\n",l,r); 62 printf("%d\n",q[r]-q[l-1]); 63 } 64 return 0; 65 }