HDU 6621 K-th Closest Distance(二分、主席树)
http://acm.hdu.edu.cn/showproblem.php?pid=6621
题意
查询在区间[L,R]内离p第k近的距离,强制在线。
题解
二分答案,建立主席树。
sum[i]表示在i节点管辖的这个区间[l,r]有多少个数的前缀和。
看博客没看懂,看队友代码学会了主席树,还有谁。
代码风格参考自ccsu_cat
1 #define bug(x) cout<<#x<<" is "<<x<<endl 2 #define IO std::ios::sync_with_stdio(0) 3 #include <bits/stdc++.h> 4 #define iter ::iterator 5 using namespace std; 6 typedef long long ll; 7 typedef pair<ll,ll>P; 8 typedef pair<P,P>P1; 9 #define mk make_pair 10 #define pb push_back 11 #define se second 12 #define fi first 13 const int N=1e5+5; 14 ll mod=998244353; 15 int n,q,cnt; 16 int rt[N],ls[N*22],rs[N*22],sum[N*22]; 17 void up(int &o,int pre,int l,int r,int p){ 18 o=++cnt; 19 sum[o]=sum[pre]+1; 20 ls[o]=ls[pre]; 21 rs[o]=rs[pre]; 22 if(l==r)return; 23 int m=(l+r)/2; 24 if(p<=m)up(ls[o],ls[pre],l,m,p); 25 else up(rs[o],rs[pre],m+1,r,p); 26 } 27 int qu(int o,int pre,int l,int r,int ql,int qr){ 28 if(l>=ql&&r<=qr){ 29 return sum[o]-sum[pre]; 30 } 31 int res=0; 32 int m=(l+r)/2; 33 if(ql<=m)res+=qu(ls[o],ls[pre],l,m,ql,qr); 34 if(qr>m)res+=qu(rs[o],rs[pre],m+1,r,ql,qr); 35 return res; 36 } 37 int check(int p,int x,int ql,int qr,int h,int k){ 38 int res=qu(rt[qr],rt[ql-1],1,h,max(1,p-x),min(p+x,h)); 39 if(res>=k)return 1; 40 return 0; 41 } 42 int main(){ 43 int T; 44 scanf("%d",&T); 45 int h=1e6; 46 while(T--){ 47 scanf("%d%d",&n,&q); 48 for(int i=1;i<=n;i++){ 49 int x; 50 scanf("%d",&x); 51 up(rt[i],rt[i-1],1,h,x); 52 } 53 cnt=0; 54 int ans=0; 55 while(q--){ 56 int ql,qr,p,k; 57 scanf("%d%d%d%d",&ql,&qr,&p,&k); 58 ql^=ans,qr^=ans,p^=ans,k^=ans; 59 int l=0,r=1e6; 60 while(l<r){ 61 int m=(l+r)/2; 62 if(check(p,m,ql,qr,h,k)){ 63 r=m; 64 } 65 else l=m+1; 66 } 67 printf("%d\n",ans=r); 68 } 69 } 70 }
队友代码,给入门主席树用。
1 #define bug(x) cout<<#x<<" is "<<x<<endl 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int maxn = 1e5 + 10, N = 1e6; 5 int rt[maxn], ls[maxn * 22], rs[maxn * 22], sum[maxn * 22], cnt; 6 #define m (l + r) / 2 7 void up(int &o, int pre, int l, int r, int k) { 8 o = ++cnt; 9 sum[o] = sum[pre] + 1; 10 ls[o] = ls[pre]; 11 rs[o] = rs[pre]; 12 if (l == r){ 13 return; 14 } 15 if (k <= m) 16 up(ls[o], ls[pre], l, m, k); 17 else 18 up(rs[o], rs[pre], m + 1, r, k); 19 } 20 int qu(int o, int pre, int l, int r, int ql, int qr) { 21 printf("l= %d r= %d\n",l,r); 22 printf("sum[%d]= %d sum[%d]= %d\n",o,sum[o],pre,sum[pre]); 23 puts(""); 24 if (l >= ql && r <= qr) 25 return sum[o] - sum[pre]; 26 int res = 0; 27 if (ql <= m) 28 res += qu(ls[o], ls[pre], l, m, ql, qr); 29 if (qr > m) 30 res += qu(rs[o], rs[pre], m + 1, r, ql, qr); 31 return res; 32 } 33 int gao(int x, int len, int l, int r) { 34 int L = max(x - len, 1); 35 int R = min(x + len, N); 36 return qu(rt[r], rt[l - 1], 1, N, L, R); 37 } 38 int main() { 39 int n, q, x, l, r, p, k, ans = 0; 40 cnt = 0; 41 for (int i = 1; i <= 3; i++) { 42 x=i; 43 up(rt[i], rt[i - 1], 1, 5, x); 44 printf("rt[%d]= %d\n",i,rt[i]); 45 for(int i=0;i<=cnt;i++){ 46 printf("ls[%d]= %d rs[%d]= %d sum[%d]= %d\n",i,ls[i],i,rs[i],i,sum[i]); 47 } 48 printf("\n"); 49 } 50 int ql=2,qr=3; 51 int res=qu(rt[qr],rt[ql-1],1,5,1,3); 52 bug(res); 53 }