Super Mario
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4041 Accepted Submission(s): 1862
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)
1 10 10 0 5 2 7 5 4 3 8 7 7 2 8 6 3 5 0 1 3 1 1 9 4 0 1 0 3 5 5 5 5 1 4 6 3 1 5 7 5 7 3
Case 1: 4 0 0 3 1 2 0 1 5 1
题意:
查找指定区间内比x小的数的个数
思路:
稍微修改下划分树,但是不知道为什么一开始想的是二分- -,强行GG。写着很麻烦而且还是错的
划分数能很方便地求出了区间中小于等于第i个数的个数,在这个基础上稍作修改即可
/*
*/
#include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <Map>
using namespace std;
typedef long long ll;
typedef long double ld;
using namespace std;
const int maxn = 100010;
int tree[20][maxn];
int sorted[maxn];
int toleft[20][maxn];
void build(int l,int r,int dep) //模拟快排 并记录左树中比i小的个数
{
if(l == r)
return;
int mid = (l+r)>>1;
int same = mid-l+1;
for(int i = l; i <= r; i++)
{
if(tree[dep][i] < sorted[mid])
same--;
}
int lpos = l;
int rpos = mid+1;
for(int i = l; i <= r; i++)
{
if(tree[dep][i] < sorted[mid])
{
tree[dep+1][lpos++] = tree[dep][i];
}
else if(tree[dep][i] == sorted[mid] && same > 0)
{
tree[dep+1][lpos++] = tree[dep][i];
same --;
}
else
{
tree[dep+1][rpos++] = tree[dep][i];
}
toleft[dep][i] = toleft[dep][l-1] + lpos -l;
}
build(l,mid,dep+1);
build(mid+1,r,dep+1);
}
int query(int L,int R,int l,int r,int dep,int k)
{
if(l == r)
{
if(tree[dep][l] <= k)
return 1;
return 0;
}
int mid = (L+R)>>1;
int cnt = toleft[dep][r]-toleft[dep][l-1];
if(sorted[mid] > k) //如果比分界线小
{
int lpos = L+toleft[dep][l-1]-toleft[dep][L-1];
int rpos = lpos+cnt-1;
if(rpos >= lpos)
return query(L,mid,lpos,rpos,dep+1,k);
return 0;
}
else
{
int rpos = r+toleft[dep][R]-toleft[dep][r];
int lpos = rpos-(r-l-cnt);
return cnt+query(mid+1,R,lpos,rpos,dep+1,k);
}
}
int main()
{
int n,m,T;
int cas = 1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
{
scanf("%d",&sorted[i]);
tree[0][i] = sorted[i];
}
sort(sorted+1,sorted+n+1);
build(1,n,0);
int l,r,to,ans;
printf("Case %d:\n",cas++);
while(m--)
{
scanf("%d%d%d",&l,&r,&to);
l++;
r++;
ans = query(1,n,l,r,0,to);
printf("%d\n",ans);
}
}
return 0;
}
232



被折叠的 条评论
为什么被折叠?



