标签:
题意:
给N个数,M次询问,每次询问区间[L,R]内元素在[X,Y]内的个数。
思路:
和之前hdu4417一样,这里因为有要在[X,Y]区间内。
所以做两次求出[1,Y]和[1,X-1]内的元素个数,然后相减得出答案。
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"iostream" #include"map" #include"vector" #define ll long long using namespace std; struct quary { int id,x,y,c,d; } q[110000]; struct fuck { int id,s; } v[105666]; struct node { int l,r; int sum; } a[200031*4]; int mark[200021],ans[105555][2]; int cmp(fuck a,fuck b) { return a.s<b.s; } int cmp1(quary a,quary b) { return a.d<b.d; } int cmp2(quary a,quary b) { return a.c<b.c; } void init(int id,int l,int r) { a[id].l=l; a[id].r=r; a[id].sum=0; if(l==r) return ; int mid=(l+r)/2; init(id*2,l,mid); init(id*2+1,mid+1,r); } void updata(int id,int x,int y) { if(a[id].l==a[id].r && a[id].l==x) { a[id].sum+=y; return ; } int mid=(a[id].l+a[id].r)/2; if(x<=mid) updata(id*2,x,y); else updata(id*2+1,x,y); a[id].sum=a[2*id].sum+a[2*id+1].sum; } int qcont(int id,int x,int y) { if(a[id].l==x && a[id].r==y) return a[id].sum; int mid=(a[id].l+a[id].r)/2; if(y<=mid) return qcont(2*id,x,y); else if(x>mid) return qcont(2*id+1,x,y); else return qcont(2*id,x,mid)+qcont(2*id+1,mid+1,y); } int main() { int t,cas=1; cin>>t; while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%d",&v[i].s); v[i].id=i; } for(int i=0; i<m; i++) { scanf("%d%d%d%d",&q[i].x,&q[i].y,&q[i].c,&q[i].d); q[i].id=i; } sort(v+1,v+1+n,cmp); sort(q,q+m,cmp1); init(1,1,n); int j=1; for(int i=0; i<m; i++) { while(j<=n && v[j].s<=q[i].d) { updata(1,v[j].id,1); j++; } ans[q[i].id][0]=qcont(1,q[i].x,q[i].y); } sort(q,q+m,cmp2); init(1,1,n); j=1; for(int i=0; i<m; i++) { while(j<=n && v[j].s<q[i].c) { updata(1,v[j].id,1); j++; } ans[q[i].id][1]=qcont(1,q[i].x,q[i].y); } printf("Case #%d:\n",cas++); for(int i=0; i<m; i++) printf("%d\n",ans[i][0]-ans[i][1]); } return 0; }
[线段树+离线处理] upcoj 2224 Boring Counting
标签:
原文地址:http://blog.csdn.net/wdcjdtc/article/details/45037927