可持久化线段树
裸可持久化线段树,把区间第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\n",query(l-1,r,(r-l+1)>>1)); 63 } 64 return 0; 65 } 66
时间: 2024-11-08 12:46:10