【BZOJ】【3524】【POI2014】Couriers

可持久化线段树

  裸可持久化线段树,把区间第K大的rank改成num即可……(往儿子走的时候不减少)

苦逼的我……MLE了一次(N*30),RE了一次(N*10)……数组大小不会开……

最后开成N*20的过了

 1 /**************************************************************
 2     Problem: 3524
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:5752 ms
 7     Memory:120416 kb
 8 ****************************************************************/
 9  
10 //BZOJ 3524
11 #include<cstdio>
12 #include<cstdlib>
13 #include<cstring>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 using namespace std;
20  
21 int getint(){
22     int v=0,sign=1; char ch=getchar();
23     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
24     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
25     return v*=sign;
26 }
27 /*******************tamplate********************/
28 const int N=500010;
29 struct Tree{
30     int cnt,l,r;
31 }t[N*20];
32 int root[N],n,m,cnt;
33 #define mid (l+r>>1)
34 void update(int &o,int l,int r,int pos){
35     t[++cnt]=t[o]; o=cnt; ++t[o].cnt;
36     if (l==r) return;
37     if (pos<=mid) update(t[o].l,l,mid,pos);
38     else update(t[o].r,mid+1,r,pos);
39 }
40 int query(int i,int j,int num){
41     i=root[i],j=root[j];
42     int l=1,r=n;
43     while(l!=r){
44         if (t[t[j].l].cnt-t[t[i].l].cnt>num)
45             r=mid,j=t[j].l,i=t[i].l;
46         else if (t[t[j].r].cnt-t[t[i].r].cnt>num)
47             l=mid+1,j=t[j].r,i=t[i].r;
48         else return 0;
49     }
50     return l;
51 }
52 #undef mid
53 int main(){
54     n=getint(),m=getint();
55     F(i,1,n){
56         root[i]=root[i-1];
57         update(root[i],1,n,getint());
58     }
59      
60     F(i,1,m){
61         int l=getint(),r=getint();
62         printf("%d
",query(l-1,r,(r-l+1)>>1));
63     }
64     return 0;
65 }
66 
View Code
原文地址:https://www.cnblogs.com/Tunix/p/4294424.html