2 1 1 5 10 4 2 3 1 4 4 8 1 4 6
Case #1: 0 Case #2: 1 21
这题需要用到离散化,因为10^9建立线段树会超时,而给的数字总共只有2*n+m,所以可以先离散化,(这里注意因为最后询问的时候所查询的时间可能没有在前n对出现,如果只对n对数字离散化,后面询问的时候会出错),我的离散化是先构造一个结构体储存输入的2*n+m的数的数字num和编号id,然后对关键词num排序,去重后用map<int,int>匹配编号,匹配完后再对id排序复原。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define maxn 300006 int sum,pos[maxn]; struct node{ int l,r,sum; }b[4*maxn]; struct edge{ int id,num; }a[maxn]; bool cmp1(edge a,edge b){ return a.num<b.num; } bool cmp2(edge a,edge b){ return a.id<b.id; } void build(int l,int r,int i) { int mid; b[i].l=l;b[i].r=r;b[i].sum=0; if(l==r)return; mid=(l+r)/2; build(l,mid,i*2); build(mid+1,r,i*2+1); } void update(int l,int r,int i) { int mid; if(b[i].l==l && b[i].r==r){ b[i].sum++;return; } mid=(b[i].l+b[i].r)/2; if(r<=mid)update(l,r,i*2); else if(l>mid)update(l,r,i*2+1); else { update(l,mid,i*2); update(mid+1,r,i*2+1); } } void question(int id,int i) { int mid; if(b[i].l==b[i].r){ sum=b[i].sum;return; } b[i*2].sum+=b[i].sum; b[i*2+1].sum+=b[i].sum; b[i].sum=0; mid=(b[i].l+b[i].r)/2; if(id<=mid)question(id,i*2); else question(id,i*2+1); } int main() { int n,m,i,j,T,h,c,d,t; map<int,int>hash; scanf("%d",&T); for(h=1;h<=T;h++){ printf("Case #%d:\n",h); scanf("%d%d",&n,&m); build(1,maxn,1); for(i=1;i<=n;i++){ scanf("%d%d",&a[i].num,&a[i+n].num); a[i].id=i;a[i+n].id=i+n; } for(i=1;i<=m;i++){ scanf("%d",&a[i+2*n].num); a[i+2*n].id=i+2*n; } sort(a+1,a+2*n+m+1,cmp1); hash[a[1].num]=1;t=1; for(i=2;i<=2*n+m;i++){ if(a[i].num!=a[i-1].num){ t++;hash[a[i].num]=t; } } sort(a+1,a+2*n+m+1,cmp2); for(i=1;i<=n;i++){ c=hash[a[i].num];d=hash[a[i+n].num]; //printf("%d %d\n",c,d); update(c,d,1); } for(i=1;i<=m;i++){ c=hash[a[i+2*n].num]; sum=0; question(c,1); printf("%d\n",sum); } } return 0; }
原文地址:http://blog.csdn.net/kirito_acmer/article/details/46276517