山東省第四屆ACM大學生程式設計競賽-Boring Counting(劃分樹-二分查詢)
Boring Counting
Time Limit: 3000ms Memory limit: 65536K 有疑問?點這裡^_^
題目描述
In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence. Now you task is to answer a list of queries,
for each query, please tell us among [L, R], how many Pi is not less than A and not greater than B( L<= i <= R). In other words, your task is to count the number of Pi (L <= i <= R, A <= Pi <= B).
輸入
In the first line there is an integer T (1 < T <= 50), indicates the number of test cases.
For each case, the first line contains two numbers N and M (1 <= N, M <= 50000), the size of sequence P, the number of queries. The second line contains N numbers Pi(1 <= Pi <= 10^9), the number sequence P. Then there are M lines, each line contains four number L, R, A, B(1 <= L, R <= n, 1 <= A, B <= 10^9)
For each case, the first line contains two numbers N and M (1 <= N, M <= 50000), the size of sequence P, the number of queries. The second line contains N numbers Pi(1 <= Pi <= 10^9), the number sequence P. Then there are M lines, each line contains four number L, R, A, B(1 <= L, R <= n, 1 <= A, B <= 10^9)
輸出
For each case, at first output a line ‘Case #c:’, c is the case number start from 1. Then for each query output a line contains the answer.
示例輸入
1 13 5 6 9 5 2 3 6 8 7 3 2 5 1 4 1 13 1 10 1 13 3 6 3 6 3 6 2 8 2 8 1 9 1 9
示例輸出
Case #1: 13 7 3 6 9
提示
來源
2013年山東省第四屆ACM大學生程式設計競賽
之前寫過遍歷查詢直接超時……用二分的效率很高。
題目意思:
求每組數中,在l~r的範圍內,有多少個數的值在a~b的範圍內。解題思路:
劃分樹+二分查詢。之前寫過遍歷查詢直接超時……用二分的效率很高。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 50050
using namespace std;
int sorted[N]; //排序完的陣列
int toleft[30][N]; //toleft[i][j]表示第i層從1到k有多少個數分入左邊
int tree[30][N]; //表示每層每個位置的值
int n;
void building(int l,int r,int dep)
{
if(l==r) return;
int mid = (l+r)>>1;
int temp = sorted[mid];
int i,sum=mid-l+1; //表示等於中間值而且被分入左邊的個數
for(i=l; i<=r; i++)
if(tree[dep][i]<temp)
sum--;
int leftpos = l;
int rightpos = mid+1;
for(i=l; i<=r; i++)
{
if(tree[dep][i]<temp) //比中間的數小,分入左邊
tree[dep+1][leftpos++]=tree[dep][i];
else if(tree[dep][i]==temp&&sum>0) //等於中間的數值,分入左邊,直到sum==0後分到右邊
{
tree[dep+1][leftpos++]=tree[dep][i];
sum--;
}
else //右邊
tree[dep+1][rightpos++]=tree[dep][i];
toleft[dep][i] = toleft[dep][l-1] + leftpos - l; //從1到i放左邊的個數
}
building(l,mid,dep+1);
building(mid+1,r,dep+1);
}
//查詢區間第k大的數,[L,R]是大區間,[l,r]是要查詢的小區間
int query(int L,int R,int l,int r,int dep,int k)
{
if(l==r) return tree[dep][l];
int mid = (L+R)>>1;
int cnt = toleft[dep][r] - toleft[dep][l-1]; //[l,r]中位於左邊的個數
if(cnt>=k)
{
int newl = L + toleft[dep][l-1] - toleft[dep][L-1]; //L+要查詢的區間前被放在左邊的個數
int newr = newl + cnt - 1; //左端點加上查詢區間會被放在左邊的個數
return query(L,mid,newl,newr,dep+1,k);
}
else
{
int newr = r + (toleft[dep][R] - toleft[dep][r]);
int newl = newr - (r-l-cnt);
return query(mid+1,R,newl,newr,dep+1,k-cnt);
}
}
int MAXA(int L,int R,int l,int r,int a) //二分列舉
{
int ans=-1;
while(l<=r)
{
int mid = (l+r)>>1;
int res = query(1,n,L,R,0,mid);
if(res>=a) //直到找到最左邊的那個等於a的結果
{
r = mid - 1;
ans = mid;
}
else l = mid + 1;
}
return ans;
}
int MINB(int L,int R,int l,int r,int b)
{
int ans=0;
while(l<=r)
{
int mid = (l+r)>>1;
int res = query(1,n,L,R,0,mid);
if(res>b) //直到找到最後邊的大於b的結果
{
r = mid - 1;
ans = mid;
}
else l = mid + 1;
}
if(!ans) return r;
return ans-1;
}
int main()
{
int t,cas = 1;
scanf("%d",&t);
while(t--)
{
int m;
scanf("%d%d",&n,&m);
int i;
for(i=1; i<=n; i++)
{
scanf("%d",&tree[0][i]);
sorted[i] = tree[0][i];
}
sort(sorted+1,sorted+1+n);
building(1,n,0);
int l,r,a,b;
printf("Case #%d:\n",cas++);
while(m--)
{
scanf("%d%d%d%d",&l,&r,&a,&b);
int x = 1;
int y = r-l+1;
int cnt1 = MAXA(l,r,x,y,a);
int cnt2 = MINB(l,r,x,y,b);
if(cnt1==-1)
{
printf("0\n");
continue;
}
printf("%d\n",cnt2-cnt1+1);
}
}
return 0;
}
/**************************************
Problem id : SDUT OJ 2610
User name : 吃花的栗鼠
Result : Accepted
Take Memory : 7260K
Take Time : 1230MS
Submit Time : 2016-05-07 20:27:46
**************************************/
相關文章
- 第十屆山東省大學生程式設計競賽題解(A、F、M、C)程式設計
- 第15屆浙江省大學生程式設計競賽D題程式設計
- 第二十屆西南科技大學ACM程式設計競賽(同步賽)ACM程式設計
- 2019山東ACM省賽補題題解ACM
- 無錫學院2024年ACM大學生程式設計競賽校選賽 題解ACM程式設計
- [題解][2021-2022年度國際大學生程式設計競賽第10屆陝西省程式設計競賽] Type The Strings程式設計
- 2020 年第一屆遼寧省大學生程式設計競賽 D.開心消消樂(點分治)程式設計
- 紹興市大學生程式設計競賽程式設計
- 第 10 屆 CCPC 中國大學生程式設計競賽濟南站 遊記程式設計
- 24山東省賽wp
- [補題] 第 45 屆國際大學生程式設計競賽(ICPC)亞洲區域賽(上海)程式設計
- 華中農業大學第十三屆程式設計競賽程式設計
- 第十屆中國大學生程式設計競賽 重慶站(CCPC 2024 Chongqing Site)程式設計
- 第43屆ACM-ICPC國際大學生程式設計競賽 亞洲區域賽南京站現場賽名額分配相關說明ACM程式設計
- 圖解--二分查詢樹圖解
- 2024 CCPC第五屆遼寧省程式設計競賽 集訓2程式設計
- 九州信泰杯 第十一屆山東省網路安全技能大賽
- 華中農業大學第十三屆程式設計競賽 題解程式設計
- 第二屆“祥雲杯”網路安全大賽暨吉林省第四屆大學生網路安全大賽火熱報名中
- 北京資訊科技大學第十一屆程式設計競賽(重現賽)I程式設計
- 查詢——二分查詢
- 中國計量大學現代科技學院第四屆“中競杯”程式設計校賽(同步賽) F.爬塔(DP)程式設計
- 湖南大學2020屆ACM新生賽 部分題解ACM
- 大學生電子設計競賽電源資料
- 二分查詢(一)——純粹的二分查詢
- 資料競賽:第四屆工業大資料競賽-虛擬測量大資料
- 二分查詢
- 2020年廣東工業大學第十屆文遠知行杯新生程式設計競賽 A.肥豬的鋼琴床(dp動態規劃)程式設計動態規劃
- 第十五屆浙江大學寧波理工學院程式設計大賽(同步賽)程式設計
- 2020年“感恩杯”台州學院第十三屆大學生程式設計競賽D、H、I題解(後續補充)程式設計
- 10.5組隊訓練賽-2024CCPC山東省賽
- 第十七屆中國計量大學程式設計競賽 I- Isolated Pointset程式設計
- 2019年第二屆全國大學生大資料技能競賽通知大資料
- 資訊學奧賽初賽天天練-81-NOIP2015普及組-完善程式-二分答案、二分查詢、中位數、二分邊界、二分時間複雜度時間複雜度
- QZEZ第一屆“飯吉圓”杯程式設計競賽程式設計
- M-災難預警-浙江農林大學第十九屆程式設計競賽暨天梯賽選拔賽程式設計
- 2024CCPC山東省賽補題記錄
- 第十四屆全國大學生資訊保安競賽——創新實踐能力賽(東北賽區)比賽圓滿落幕
- 第二屆“重科杯”重慶科技大學程式設計競賽(同步賽)ptlks的題解(2024.5.18)程式設計