题目:
Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss’s castle as a line (the length is n), on every integer point i there is a brick on height hi. Now the question is how many bricks in [L, R] Mario can hit if the maximal height he can jump is H.
思路:
做法一:按 数值大小不断的回归数组,离线统计区间中 1的个数。
做法二:对于每个 L != 0 的区间,我们都增加一个新区间 [0,L-1],这样我们结果就转化为区间[0,R] 的值 减去 [0,L-1]的值 .比上述方法慢 30ms 左右 (也有可能自己写搓了 )。
参考代码
#include <iostream>
#include <algorithm>
using namespace std;
struct QJ
{
int l,r,h;
int num;
int f;
};
QJ s[100050];
int n,len,m;
int a[100050];
int v[100050];
int c[100050];
int ans[100050];
bool cmp(const QJ& a,const QJ& b) {
return a.r == b.r? a.l<b.l:a.r<b.r;
}
int lowbit(int x) {
return x&-x;
}
void update(int pos,int d) {
while(pos<=len) {
c[pos] += d;
pos += lowbit(pos);
}
return ;
}
int getsum(int pos) {
int ans = 0;
while(pos>0) {
ans += c[pos];
pos -= lowbit(pos);
}
return ans;
}
int main() {
int t;int cases = 1;
cin>>t;
while(t--) {
int now = 0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
v[i-1] = a[i];
c[i] = 0;
}
sort(v,v+n);
len = unique(v,v+n) -v;
for(int i=0;i<m;i++) {
ans [i] = 0;
scanf("%d%d%d",&s[now].l,&s[now].r,&s[now].h);
s[now].l++;s[now].r++;
s[now].num = i; s[now].f = 1;
now++;
if(s[now-1].l!=1) {
s[now].l = 1;
s[now].r = s[now-1].l-1;
s[now].h = s[now-1].h;
s[now].num=i;
s[now].f = -1;
now++;
}
}
int pre = 0;
sort(s,s+now,cmp);
for(int i=1;i<=n;i++) {
if(pre == now) break;
int temp = lower_bound(v,v+len,a[i])-v +1;
update(temp,1);
while(pre<now&& s[pre].r<=i) {
int temps = upper_bound(v,v+len,s[pre].h) - v +1;
ans[s[pre].num] += s[pre].f * (getsum(temps-1));
// cout << s[pre].num << ' '<<ans[s[pre].num]<<endl;
pre++;
}
}
printf("Case %d:\n",cases++);
for(int i=0;i<m;i++) {
printf("%d\n",ans[i]);
}
}
return 0;
}