hdu 4417 Super Mario

来源:互联网 发布:肇庆市房地产数据 编辑:程序博客网 时间:2024/05/02 06:12

Super Mario

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1028    Accepted Submission(s): 519


Problem Description
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.
 

Input
The first line follows an integer T, the number of test data.
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.)
 

Output
For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.
 

Sample Input
110 100 5 2 7 5 4 3 8 7 7 2 8 63 5 01 3 11 9 40 1 03 5 55 5 14 6 31 5 75 7 3
 

Sample Output
Case 1:4003120151
 

Source
2012 ACM/ICPC Asia Regional Hangzhou Online 

分析:求区间[L,R]内不大于H的数有几个。做法:求区间第K小的数,二分枚举K
#include<cstdio>#include<algorithm>using namespace std;const int N=100001;int arr[N],sorted[N],val[18][N],toleft[18][N],n;void build(int l,int r,int d){if(l==r)return;int m=(l+r)>>1;int same=m-l+1,i=l,j=m+1,k;for(k=l;k<=r;k++)if(val[d][k]<sorted[m])same--;for(k=l;k<=r;k++){if(val[d][k]<sorted[m])val[d+1][i++]=val[d][k];else if(val[d][k]==sorted[m]&&same>0){val[d+1][i++]=val[d][k];same--;}else val[d+1][j++]=val[d][k];toleft[d][k]=toleft[d][l-1]+i-l;}build(l,m,d+1);build(m+1,r,d+1);}int query(int L,int R,int l,int r,int d,int k){if(l==r)return val[d][l];int m=(L+R)>>1;int cnt=toleft[d][r]-toleft[d][l-1];if(cnt>=k){int nl=L+toleft[d][l-1]-toleft[d][L-1];int nr=nl+cnt-1;return query(L,m,nl,nr,d+1,k);}else{int nr=r+toleft[d][R]-toleft[d][r];int nl=nr-(r-l-cnt);return query(m+1,R,nl,nr,d+1,k-cnt);}}void cal(int L,int R,int H){L++,R++;int l=1,r=R-L+1,m,tmp;while(l<=r){m=(l+r)>>1;tmp=query(1,n,L,R,0,m);if(tmp>H)r=m-1;else l=m+1;}printf("%d\n",r);}int main(){int T,m,s,t,k,i,ca=1;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(i=1;i<=n;i++){scan_d(val[0][i]);sorted[i]=val[0][i];}sort(sorted+1,sorted+n+1);build(1,n,0);printf("Case %d:\n",ca++);while(m--){scanf("%d%d%d",&s,&t,&k);cal(s,t,k);}}return 0;}

线段树做法:将输入数据以及查询按h升序排序,对每个询问,将不大于其h的原始数据插到线段树中(即把相应位置置为1),然后区间求和即可(单点更新,区间求和)
#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N=100001;int val[N<<2],ans[N];struct node{int val,id;bool operator<(node p)const{return val<p.val;}}a[N];struct query{int l,r,h,id;bool operator<(query p)const{return h<p.h;}}q[N];void pushup(int rt){val[rt]=val[rt<<1]+val[rt<<1|1];}void build(int l,int r,int rt){val[rt]=0;if(l==r)return ;int m=(l+r)>>1;build(lson);build(rson);}void update(int p,int l,int r,int rt){if(l==r){val[rt]++;return ;}int m=(l+r)>>1;if(p<=m)update(p,lson);else update(p,rson);pushup(rt);}int query(int L,int R,int l,int r,int rt){if(L<=l&&R>=r)return val[rt];int m=(l+r)>>1,ret=0;if(L<=m)ret+=query(L,R,lson);if(R>m)ret+=query(L,R,rson);return ret;}int main(){int T,n,m,i,k,l,r,h,ca=1;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(i=0;i<n;i++)a[i].id=i+1,scanf("%d",&a[i].val);for(i=0;i<m;i++)q[i].id=i,scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);sort(a,a+n),sort(q,q+m);build(1,n,1);k=0;for(i=0;i<m;i++){while(k<n&&a[k].val<=q[i].h)update(a[k++].id,1,n,1);ans[q[i].id]=query(q[i].l+1,q[i].r+1,1,n,1);}printf("Case %d:\n",ca++);for(i=0;i<m;i++)printf("%d\n",ans[i]);}return 0;}

有上面线段树的做法,就相应有树状数组做法:
#include<cstdio>#include<algorithm>using namespace std;const int N=100001;#define lowbit(x) x&-xstruct node{    int val,id;    bool operator<(node p)const{return val<p.val;}}a[N];struct query{    int l,r,h,id;    bool operator<(query p)const{return h<p.h;}}q[N];int n,ans[N],arr[N];void inc(int val,int pos){    for(int i=pos;i<=n;i+=lowbit(i))arr[i]+=val;}int getSum(int pos){    int sum=0;    for(int i=pos;i>0;i-=lowbit(i))sum+=arr[i];    return sum;}int main(){    int T,m,i,k,l,r,h,ca=1;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        for(i=0;i<n;i++)a[i].id=i+1,scanf("%d",&a[i].val);        for(i=0;i<m;i++)q[i].id=i,scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);        sort(a,a+n),sort(q,q+m);        memset(arr,0,sizeof(arr));        k=0;        for(i=0;i<m;i++){            while(k<n&&a[k].val<=q[i].h)inc(1,a[k++].id);            ans[q[i].id]=getSum(q[i].r+1)-getSum(q[i].l);        }        printf("Case %d:\n",ca++);        for(i=0;i<m;i++)printf("%d\n",ans[i]);    }    return 0;}


原创粉丝点击