1.(HDOJ6278)http://acm.hdu.edu.cn/showproblem.php?pid=6278
2.(CF961E)http://codeforces.com/problemset/problem/961/E
3.(CF1000F)http://codeforces.com/problemset/problem/1000/F
4.(CF916D)https://www.luogu.org/problemnew/show/CF916D
5.(CQOI2015)https://www.luogu.org/problemnew/show/P3168
6.(POI2014)https://www.luogu.org/problemnew/show/P3567
7.(SCOI2016)https://www.luogu.org/problemnew/show/P3293
8.(SDOI2010)https://www.luogu.org/problemnew/show/P2468
9.(P4137)https://www.luogu.org/problemnew/show/P4137
1.(HDOJ6278)http://acm.hdu.edu.cn/showproblem.php?pid=6278
题意:给定一个长度为n的序列,和q个询问,求每个询问[l,r]中最大的h,满足该区间内至少有h个数的值大于h。
分析:主席树+二分答案。每次二分后求区间第mid小的数与mid比较
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=1e5+10; 7 const int maxm=5e6+10; 8 int n,q,m,tot; 9 int a[maxn],t[maxn]; 10 int T[maxn],lson[maxm],rson[maxm],c[maxm]; 11 12 void init_hash() 13 { 14 for ( int i=1;i<=n;i++ ) t[i]=a[i]; 15 sort(t+1,t+1+n); 16 m=unique(t+1,t+1+n)-(t+1); 17 } 18 19 int build(int l,int r) 20 { 21 int root=tot++; 22 c[root]=0; 23 if ( l!=r ) 24 { 25 int mid=(l+r)/2; 26 lson[root]=build(l,mid); 27 rson[root]=build(mid+1,r); 28 } 29 return root; 30 } 31 32 int hash_(int x) 33 { 34 return lower_bound(t+1,t+1+m,x)-t; 35 } 36 37 int update(int root,int pos,int val) 38 { 39 int rt=tot++,tmp=rt; 40 c[rt]=c[root]+val; 41 int l=1,r=m; 42 while ( l<r ) 43 { 44 int mid=(l+r)/2; 45 if ( pos<=mid ) 46 { 47 lson[rt]=tot++;rson[rt]=rson[root]; 48 rt=lson[rt];root=lson[root]; 49 r=mid; 50 } 51 else 52 { 53 rson[rt]=tot++;lson[rt]=lson[root]; 54 rt=rson[rt];root=rson[root]; 55 l=mid+1; 56 } 57 c[rt]=c[root]+val; 58 } 59 return tmp; 60 } 61 62 int query(int lrt,int rrt,int k) 63 { 64 if ( k==0 ) return 0; 65 int l=1,r=m; 66 while ( l<r ) 67 { 68 int mid=(l+r)/2; 69 if ( c[lson[rrt]]-c[lson[lrt]]>=k ) 70 { 71 r=mid; 72 lrt=lson[lrt]; 73 rrt=lson[rrt]; 74 } 75 else 76 { 77 l=mid+1; 78 k-=c[lson[rrt]]-c[lson[lrt]]; 79 lrt=rson[lrt]; 80 rrt=rson[rrt]; 81 } 82 } 83 return l; 84 } 85 86 int main() 87 { 88 int Case; 89 while ( scanf("%d%d",&n,&q)!=EOF ) 90 { 91 tot=0; 92 for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]); 93 init_hash(); 94 T[0]=build(1,m); 95 for ( int i=1;i<=n;i++ ) 96 { 97 int pos=hash_(a[i]); 98 T[i]=update(T[i-1],pos,1); 99 } 100 while ( q-- ) 101 { 102 int l,r,k,mid,L,R,num; 103 scanf("%d%d",&l,&r); 104 L=1,R=r-l+2; 105 while ( R-L>1 ) 106 { 107 mid=(L+R)/2; 108 k=t[query(T[l-1],T[r],r-l+1-mid+1)]; 109 if ( k>=mid ) L=mid; 110 else R=mid; 111 } 112 printf("%d\n",L); 113 } 114 } 115 return 0; 116 }