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 }

 

posted @ 2019-08-04 16:16  Venux  阅读(210)  评论(0编辑  收藏  举报