可持久化线段树
这次是询问一段区间内权值 在给定范围内的点的数量,同样是可持久化线段树简单操作……
1 //Vijos 1923 2 #include<vector> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 13 int getint(){ 14 int v=0,sign=1; char ch=getchar(); 15 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 17 return v*=sign; 18 } 19 #define debug 20 /*******************tamplate********************/ 21 const int N=100086; 22 23 int root[N],n,m,cnt; 24 struct Tree{ 25 int l,r,cnt; 26 }t[N*30]; 27 28 struct node{ 29 int val,num,rank; 30 bool operator < (const node&now)const{ 31 return val<now.val; 32 } 33 }a[N]; 34 int b[N]; 35 bool cmp(node a,node b){ 36 return a.num<b.num; 37 } 38 39 #define mid (l+r>>1) 40 void update(int &o,int l,int r,int pos){ 41 t[++cnt]=t[o]; o=cnt; ++t[o].cnt; 42 if(l==r)return; 43 if(pos<=mid) update(t[o].l,l,mid,pos); 44 else update(t[o].r,mid+1,r,pos); 45 } 46 47 int _sum,ql,qr; 48 void query(int i,int j,int l,int r){ 49 if (ql<=l && qr>=r) _sum+=t[j].cnt-t[i].cnt; 50 else{ 51 if (ql<=mid) query(t[i].l,t[j].l,l,mid); 52 if (qr> mid) query(t[i].r,t[j].r,mid+1,r); 53 } 54 } 55 #undef mid 56 int main(){ 57 n=getint(); m=getint(); 58 F(i,1,n) {a[i].val=getint(); a[i].num=i;} 59 sort(a+1,a+n+1); 60 int rank=0,tot=0; 61 F(i,1,n) if(a[i].val!=a[i-1].val){ 62 a[i].rank=++rank; 63 b[++tot]=a[i].val; 64 } 65 else a[i].rank=rank; 66 67 sort(a+1,a+n+1,cmp); 68 69 F(i,1,n){ 70 root[i]=root[i-1]; 71 update(root[i],1,n,a[i].rank); 72 } 73 int l,r,k,w; 74 F(i,1,m){ 75 l=getint(); r=getint(); k=getint(); w=getint(); 76 ql=lower_bound(b+1,b+tot+1,k)-b; 77 qr=upper_bound(b+1,b+tot+1,w)-b-1;//!!! 78 _sum=0; 79 query(root[l-1],root[r],1,n); 80 printf("%d ",_sum); 81 } 82 return 0; 83 }