hdoj 4325 Flowers
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4325
思路:
直接线段树,按照花的开放区间的大小建树,要注意虽然花的周期数据可能会达到1e9,这样的话线段树开四倍时不可能的。但是我们可以看到一共可能的数据时N行,那么每行两个数,再开4倍的区间。计算下来,在离散化的帮助下,我们只需要开8*N被的线段树即可。
另外询问的数据也需要放入离散化的范围,如果不这样做,有可能在询问时使用lower_bound函数会导致数据的改变,询问的原数据发生变化。
eg:1~3 7~10 询问6,结果应该时0,但因为lower_bound的原因询问时使用7,得到结果1。etc.
代码:
#include <iostream> #include <algorithm> #include <stdio.h> #include <string.h> #include <math.h> using namespace std; const int maxn = 1e5+5; struct node { int l,r,sum,lazy; inline void update(int val) { lazy+=val; sum+=val; } } tr[maxn*8]; int a[maxn],b[maxn],c[maxn<<1],d[maxn]; inline void push_down(int s) { int lazyval = tr[s].lazy; if(!lazyval) return; tr[s<<1].update(lazyval); tr[s<<1|1].update(lazyval); tr[s].lazy=0; } void build(int s, int l, int r) { tr[s].l=l;tr[s].r=r; tr[s].lazy=tr[s].sum=0; if(l==r) return; int mid = (l+r)>>1; build(s<<1,l,mid); build(s<<1|1,mid+1,r); } void update(int s, int l, int r) { if(tr[s].l==l&&tr[s].r==r) { tr[s].update(1); return; } push_down(s); int mid = (tr[s].l+tr[s].r)>>1; if(r<=mid) update(s<<1,l,r); else if(l>mid) update(s<<1|1,l,r); else { update(s<<1,l,mid); update(s<<1|1,mid+1,r); } } int query(int s, int l, int r) { if(tr[s].l==l&&tr[s].r==r) { return tr[s].sum; } push_down(s); int mid=(tr[s].l+tr[s].r)>>1; if(r<=mid) return query(s<<1,l,r); else return query(s<<1|1,l,r); } int main() { int t,n,m,tot; scanf("%d",&t); for(int j=1;j<=t;++j) { scanf("%d %d",&n,&m); tot=1; for(int i=1;i<=n;++i) { scanf("%d %d",&a[i],&b[i]); c[tot++]=a[i];c[tot++]=b[i]; } for(int i=1;i<=m;++i) { scanf("%d",&d[i]); c[tot++]=d[i]; } sort(c+1,c+tot); tot=unique(c+1,c+tot)-(c+1); build(1,1,tot); for(int i=1;i<=n;++i) { a[i]=lower_bound(c+1,c+tot,a[i])-c; b[i]=lower_bound(c+1,c+tot,b[i])-c; update(1,a[i],b[i]); } printf("Case #%d:\n",j); for(int i=1;i<=m;++i) { d[i]=lower_bound(c+1,c+tot,d[i])-c; printf("%d\n",query(1,d[i],d[i])); } } return 0; }
来源:https://www.cnblogs.com/lemonbiscuit/p/7899253.html