标签:des style color io os ar for sp div
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
普通的线段树果断T成狗,故转向离线。
将砖块高度val和玛丽能跳的高度H都存起来,更新p[k].val<=q[i].h的,区间求和的时候就能保证当前更新的都是小于玛丽能跳的的高度。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<limits.h> typedef long long LL; using namespace std; const int maxn=1e5+10; struct tree{ int l,r; int cnt; }t[maxn<<2]; struct node1{ int val; int pos; bool operator<(const node1 l1)const{ return val<l1.val; } }p[maxn];//保存玛丽的原始位置和能跳的高度 struct node2{ int l,r; int id,h; bool operator<(const node2 l2)const{ return h<l2.h; } }q[maxn];//保存m次询问 int ans[maxn]; void pushup(int rs) { t[rs].cnt=t[rs<<1].cnt+t[rs<<1|1].cnt; } void build(int rs,int l,int r) { t[rs].l=l; t[rs].r=r; t[rs].cnt=0; if(l==r) return ; int mid=(l+r)>>1; build(rs<<1,l,mid); build(rs<<1|1,mid+1,r); } void update(int rs,int pos) { t[rs].cnt++; if(t[rs].l==t[rs].r) return ; int mid=(t[rs].l+t[rs].r)>>1; if(pos<=mid) update(rs<<1,pos); else update(rs<<1|1,pos); } int query(int l,int r,int rs) { if(t[rs].l==l&&t[rs].r==r) return t[rs].cnt; int mid=(t[rs].l+t[rs].r)>>1; if(r<=mid) return query(l,r,rs<<1); else if(l>mid) return query(l,r,rs<<1|1); else return query(l,mid,rs<<1)+query(mid+1,r,rs<<1|1); } int main() { int t,n,m; int cas=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(1,1,n); for(int i=1;i<=n;i++) { scanf("%d",&p[i].val); p[i].pos=i; } for(int i=1;i<=m;i++) { scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h); q[i].id=i; } sort(p+1,p+1+n); sort(q+1,q+1+m); int k=1; for(int i=1;i<=m;i++) { while(k<=n&&p[k].val<=q[i].h) { update(1,p[k].pos); k++; } ans[q[i].id]=query(q[i].l+1,q[i].r+1,1); } printf("Case %d:\n",cas++); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }
另外树状数组也可以做。类似的单点更新和区间求和问题都可以用树状数组来写。
类似离线线段树的思想将节点和询问保存排序后依次更新,就能保证结果的正确性。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<limits.h> typedef long long LL; using namespace std; const int maxn=1e5+10; int cnt[maxn]; struct node1{ int val; int pos; bool operator<(const node1 l1)const{ return val<l1.val; } }p[maxn];//保存玛丽的原始位置和能跳的高度 struct node2{ int l,r; int id,h; bool operator<(const node2 l2)const{ return h<l2.h; } }q[maxn];//保存m次询问 int ans[maxn]; int lowbit(int x) { return x&(-x); } void update(int x) { while(x<maxn) { cnt[x]++; x+=lowbit(x); } } int query(int x) { int s=0; while(x>0) { s+=cnt[x]; x-=lowbit(x); } return s; } int main() { int t,n,m; int cas=1; scanf("%d",&t); while(t--) { memset(cnt,0,sizeof(cnt)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&p[i].val); p[i].pos=i; } for(int i=1;i<=m;i++) { scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h); q[i].id=i; } sort(p+1,p+1+n); sort(q+1,q+1+m); int k=1; for(int i=1;i<=m;i++) { while(k<=n&&p[k].val<=q[i].h) { update(p[k].pos); k++; } ans[q[i].id]=query(q[i].r+1)-query(q[i].l); } printf("Case %d:\n",cas++); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }
HDU 4417 Super Mario(离线线段树or树状数组)
标签:des style color io os ar for sp div
原文地址:http://blog.csdn.net/u013582254/article/details/39584745