题意:输入一个长度为n的序列,然后m个询问,询问区间[a,b]中比h小的数的个数。
思路:树状数组或线段树离线处理。
树状数组1
View Code
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 9 #define repd(i,a,b) for(int i=(a);i>=(b);i--) 10 #define N 100010 11 typedef __int64 ll; 12 int c[N],val[N]; 13 struct edge{ 14 int a,b,w,pos; 15 }e[N*2]; 16 bool cmp(edge a,edge b){ 17 if(a.w==b.w){ 18 return a.pos<b.pos; 19 } 20 return a.w<b.w; 21 } 22 int lowbit(int x){ 23 return x&(-x); 24 } 25 int sum(int pos){ 26 int s=0; 27 while(pos>0){ 28 s+=c[pos]; 29 pos-=lowbit(pos); 30 } 31 return s; 32 } 33 void add(int pos,int x,int n){ 34 while(pos<=n){ 35 c[pos]+=x; 36 pos+=lowbit(pos); 37 } 38 } 39 int main(){ 40 int ca,cas=1; 41 scanf("%d",&ca); 42 while(ca--){ 43 memset(c,0,sizeof(c)); 44 int n,m; 45 scanf("%d%d",&n,&m); 46 rep(i,1,n){ 47 scanf("%d",&e[i].w); 48 e[i].a=e[i].b=-1; 49 e[i].pos=i; 50 } 51 rep(i,n+1,m+n){ 52 scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].w); 53 e[i].pos=i; 54 } 55 sort(e+1,e+m+n+1,cmp); 56 rep(i,1,m+n){ 57 if(e[i].pos>n){ 58 val[e[i].pos-n]=sum(e[i].b+1)-sum(e[i].a); 59 } 60 else add(e[i].pos,1,n); 61 } 62 printf("Case %d:\n",cas++); 63 rep(i,1,m){ 64 printf("%d\n",val[i]); 65 } 66 } 67 return 0; 68 }
树状数组2
View Code
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 9 #define repd(i,a,b) for(int i=(a);i>=(b);i--) 10 #define N 100010 11 typedef __int64 ll; 12 int c[N],val[N]; 13 struct edge{ 14 int a,b,w,pos; 15 }e[N*2]; 16 bool cmp(edge a,edge b){ 17 if(a.w==b.w){ 18 return a.pos<b.pos; 19 } 20 return a.w<b.w; 21 } 22 struct Tary{ 23 int c[N]; 24 void init(){ 25 memset(c,0,sizeof(c)); 26 } 27 int lowbit(int x){ 28 return x&(-x); 29 } 30 int sum(int pos){ 31 int s=0; 32 for(int i=pos;i>0;i-=lowbit(i))s+=c[i]; 33 return s; 34 } 35 void add(int pos,int x,int n){ 36 for(int i=pos;i<=n;i+=lowbit(i))c[i]+=x; 37 } 38 }tre; 39 int main(){ 40 int ca,cas=1; 41 scanf("%d",&ca); 42 while(ca--){ 43 tre.init(); 44 int n,m; 45 scanf("%d%d",&n,&m); 46 rep(i,1,n){ 47 scanf("%d",&e[i].w); 48 e[i].a=e[i].b=-1; 49 e[i].pos=i; 50 } 51 rep(i,n+1,m+n){ 52 scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].w); 53 e[i].pos=i; 54 } 55 sort(e+1,e+m+n+1,cmp); 56 rep(i,1,m+n){ 57 if(e[i].pos>n){ 58 val[e[i].pos-n]=tre.sum(e[i].b+1)-tre.sum(e[i].a); 59 } 60 else tre.add(e[i].pos,1,n); 61 } 62 printf("Case %d:\n",cas++); 63 rep(i,1,m){ 64 printf("%d\n",val[i]); 65 } 66 } 67 return 0; 68 }
线段树
View Code
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 9 #define repd(i,a,b) for(int i=(a);i>=(b);i--) 10 #define lson a,m,k<<1 11 #define rson m+1,b,k<<1|1 12 #define N 100010 13 typedef __int64 ll; 14 int val[N]; 15 struct edge{ 16 int a,b,w,pos; 17 }e[N*2]; 18 bool cmp(edge a,edge b){ 19 if(a.w==b.w){ 20 return a.pos<b.pos; 21 } 22 return a.w<b.w; 23 } 24 struct SegTre{ 25 struct Treenode{ 26 int a,b,sum; 27 }tree[N*3]; 28 void pushup(int k){ 29 tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum; 30 } 31 void bulid(int a,int b,int k){ 32 tree[k].a=a,tree[k].b=b,tree[k].sum=0; 33 if(a==b)return ; 34 int m=(a+b)>>1; 35 bulid(lson);bulid(rson);pushup(k); 36 } 37 void update(int pos,int a,int b,int k){ 38 if(a==b){tree[k].sum+=1;return ;} 39 int m=(a+b)>>1; 40 if(pos<=m)update(pos,lson); 41 else update(pos,rson); 42 pushup(k); 43 } 44 int query(int c,int d,int a,int b,int k){ 45 if(c<=a&&d>=b)return tree[k].sum; 46 int m=(a+b)>>1; 47 int t=0; 48 if(c<=m)t=query(c,d,lson); 49 if(d>m)t+=query(c,d,rson); 50 return t; 51 } 52 }tre; 53 int main(){ 54 int ca,cas=1; 55 scanf("%d",&ca); 56 while(ca--){ 57 58 int n,m; 59 scanf("%d%d",&n,&m); 60 tre.bulid(1,n,1); 61 rep(i,1,n){ 62 scanf("%d",&e[i].w); 63 e[i].a=e[i].b=-1; 64 e[i].pos=i; 65 } 66 rep(i,n+1,m+n){ 67 scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].w); 68 e[i].pos=i; 69 } 70 sort(e+1,e+m+n+1,cmp); 71 rep(i,1,m+n){ 72 if(e[i].pos>n){ 73 val[e[i].pos-n]=tre.query(e[i].a+1,e[i].b+1,1,n,1); 74 } 75 else tre.update(e[i].pos,1,n,1); 76 } 77 printf("Case %d:\n",cas++); 78 rep(i,1,m){ 79 printf("%d\n",val[i]); 80 } 81 } 82 return 0; 83 }
划分树+二分
View Code
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 8 #define lson L,M,dep+1 9 #define rson M+1,R,dep+1 10 #define N 100010 11 struct PartTree{ 12 int sorted[N]; 13 int toleft[30][N]; 14 int tree[30][N]; 15 void init(int n){ 16 rep(i,1,n)tree[0][i]=sorted[i]; 17 sort(sorted+1,sorted+n+1); 18 } 19 void bulid(int L,int R,int dep){ 20 if(L==R)return ; 21 int M=(L+R)>>1,same=M-L+1; 22 rep(i,L,R){ 23 if(sorted[M]>tree[dep][i])same--; 24 } 25 int lpos=L,rpos=M+1; 26 rep(i,L,R){ 27 if(tree[dep][i]<sorted[M])tree[dep+1][lpos++]=tree[dep][i]; 28 else if(sorted[M]==tree[dep][i]&&same)tree[dep+1][lpos++]=tree[dep][i],same--; 29 else tree[dep+1][rpos++]=tree[dep][i]; 30 toleft[dep][i]=toleft[dep][L-1]+lpos-L; 31 } 32 bulid(lson); 33 bulid(rson); 34 } 35 int query(int L,int R,int dep,int l,int r,int k){ 36 if(l==r)return tree[dep][l]; 37 int M=(L+R)>>1; 38 int cnt=toleft[dep][r]-toleft[dep][l-1]; 39 if(cnt>=k){ 40 int newl=L+toleft[dep][l-1]-toleft[dep][L-1]; 41 int newr=newl+cnt-1; 42 return query(lson,newl,newr,k); 43 } 44 else { 45 int newr=r+toleft[dep][R]-toleft[dep][r]; 46 int newl=newr-(r-l-cnt); 47 return query(rson,newl,newr,k-cnt); 48 } 49 } 50 }tre; 51 int slove(int a,int b,int w,int n){ 52 int left=1,right=b-a+1; 53 while(left<right){ 54 int mid=(left+right)>>1; 55 int t=tre.query(1,n,0,a,b,mid); 56 if(t>w)right=mid; 57 else left=mid+1; 58 } 59 if(tre.query(1,n,0,a,b,left)>w)return left-1; 60 return left; 61 } 62 int main(){ 63 int ca,cas=1; 64 scanf("%d",&ca); 65 while(ca--){ 66 int n,m; 67 scanf("%d%d",&n,&m); 68 rep(i,1,n){ 69 scanf("%d",&tre.sorted[i]); 70 } 71 tre.init(n); 72 tre.bulid(1,n,0); 73 printf("Case %d:\n",cas++); 74 rep(i,1,m){ 75 int a,b,w; 76 scanf("%d%d%d",&a,&b,&w); 77 printf("%d\n",slove(a+1,b+1,w,n)); 78 } 79 } 80 return 0; 81 }
划分树变形
View Code
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 8 #define lson L,M,dep+1 9 #define rson M+1,R,dep+1 10 #define N 100010 11 struct PartTree{ 12 int sorted[N]; 13 int toleft[30][N]; 14 int tree[30][N]; 15 void init(int n){ 16 rep(i,1,n)tree[0][i]=sorted[i]; 17 sort(sorted+1,sorted+n+1); 18 } 19 void bulid(int L,int R,int dep){ 20 if(L==R)return ; 21 int M=(L+R)>>1,same=M-L+1; 22 rep(i,L,R){ 23 if(sorted[M]>tree[dep][i])same--; 24 } 25 int lpos=L,rpos=M+1; 26 rep(i,L,R){ 27 if(tree[dep][i]<sorted[M])tree[dep+1][lpos++]=tree[dep][i]; 28 else if(sorted[M]==tree[dep][i]&&same)tree[dep+1][lpos++]=tree[dep][i],same--; 29 else tree[dep+1][rpos++]=tree[dep][i]; 30 toleft[dep][i]=toleft[dep][L-1]+lpos-L; 31 } 32 bulid(lson); 33 bulid(rson); 34 } 35 int query(int L,int R,int dep,int l,int r,int w){ 36 if(l==r)return tree[dep][l]<=w?1:0; 37 else if(l>r)return 0; 38 int M=(L+R)>>1; 39 int cnt=toleft[dep][r]-toleft[dep][l-1]; 40 if(sorted[M]>w){ 41 int newl=L+toleft[dep][l-1]-toleft[dep][L-1]; 42 int newr=newl+cnt-1; 43 return query(lson,newl,newr,w); 44 } 45 else { 46 int newr=r+toleft[dep][R]-toleft[dep][r]; 47 int newl=newr-(r-l-cnt); 48 return query(rson,newl,newr,w)+cnt; 49 } 50 } 51 }tre; 52 int slove(int a,int b,int w,int n){ 53 return tre.query(1,n,0,a,b,w); 54 } 55 int main(){ 56 int ca,cas=1; 57 scanf("%d",&ca); 58 while(ca--){ 59 int n,m; 60 scanf("%d%d",&n,&m); 61 rep(i,1,n){ 62 scanf("%d",&tre.sorted[i]); 63 } 64 tre.init(n); 65 tre.bulid(1,n,0); 66 printf("Case %d:\n",cas++); 67 rep(i,1,m){ 68 int a,b,w; 69 scanf("%d%d%d",&a,&b,&w); 70 printf("%d\n",slove(a+1,b+1,w,n)); 71 } 72 } 73 return 0; 74 }