[主席树]K-th Number

正确解法:

分块(超时)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <vector>
 9 #include <cctype>
10 #include <sstream>
11 using namespace std;
12 typedef long long ll;
13 const int inf=0x7fffffff;
14 const int N=100000+100;
15 const int M=5000+10;
16 const double PI=acos(-1.0);
17 int B=1000;
18 int n,m,a[N],num[N];
19 int I,J,K;
20 vector<int> buck[N/1000];
21 int main()
22 {
23     scanf("%d %d",&n,&m);
24     for(int i=0;i<n;i++)
25     {
26         scanf("%d",&a[i]);
27         num[i]=a[i];
28         buck[i/B].push_back(a[i]);
29     }
30     sort(num,num+n);
31     for(int i=0;i<n/B;i++)
32         sort(buck[i].begin(),buck[i].end());
33     for(int i=0;i<m;i++)
34     {
35         scanf("%d %d %d",&I,&J,&K);
36         int lb=0,ub=n-1;
37         while(lb<=ub)
38         {
39             int md= lb+ub >>1;
40             int x=num[md];
41             int tl=I-1,tr=J,c=0;
42             while(tl<tr &&tl%B!=0)  if(a[tl++]<=x)  c++;
43             while(tl<tr &&tr%B!=0)  if(a[--tr]<=x)  c++;
44             while(tl<tr)
45             {
46                 int b=tl/B;
47                 c+=upper_bound(buck[b].begin(),buck[b].end(),x)-buck[b].begin();
48                 tl+=B;
49             }
50             if(c>=K)    ub=md-1;
51             else lb=md+1;
52         }
53         printf("%d
",num[lb]);
54     }
55 
56 
57     return 0;
58 }
View Code

主席树:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <vector>
 9 #include <cctype>
10 #include <sstream>
11 using namespace std;
12 typedef long long ll;
13 const int inf=0x7fffffff;
14 const int N=100000+100;
15 const int M=5000+10;
16 const double PI=acos(-1.0);
17 int n,m,a[N],num[N];
18 int I,J,K;
19 vector<int>buck[(1<<18)-1];
20 void build(int rt,int l,int r)
21 {
22     if(l==r)
23     {
24         buck[rt].push_back(a[l]);
25         return ;
26     }
27     int m= l+r >>1;
28     build(rt<<1,l,m);
29     build(rt<<1|1,m+1,r);
30     buck[rt].resize(r-l+1);
31     merge(buck[rt<<1].begin(),buck[rt<<1].end(),buck[rt<<1|1].begin(),buck[rt<<1|1].end(),buck[rt].begin());
32 }
33 int query(int L,int R,int x,int rt,int l,int r)
34 {
35     if(R<l||r<L)
36         return 0;
37     if(L<=l&&r<=R)
38         return upper_bound(buck[rt].begin(),buck[rt].end(),x)-buck[rt].begin();
39     int ans=0,m=l+r >>1;
40     ans+=query(L,R,x,rt<<1,l,m);
41     ans+=query(L,R,x,rt<<1|1,m+1,r);
42     return ans;
43 }
44 int main()
45 {
46     scanf("%d %d",&n,&m);
47     for(int i=1;i<=n;i++)
48     {
49         scanf("%d",&a[i]);
50         num[i]=a[i];
51     }
52     sort(num+1,num+1+n);
53     build(1,1,n);
54     while(m--)
55     {
56         scanf("%d %d %d",&I,&J,&K);
57         //J++;
58         int lb=1,ub=n;
59         while(lb<=ub)
60         {
61             int md=lb+ub >>1;
62             int c=query(I,J,num[md],1,1,n);
63             if(c>=K)    ub=md-1;
64             else lb=md+1;
65         }
66         printf("%d
",num[lb]);
67     }
68 
69     return 0;
70 }
View Code
No matter how you feel, get up , dress up , show up ,and never give up.
原文地址:https://www.cnblogs.com/Kaike/p/10808572.html