链接:https://ac.nowcoder.com/acm/contest/1107/C
来源:牛客网
找一段区间内,大于等于这个数的个数大于等于这个数本身,问符合条件的最大值是多少。
思路:把数据存到主席树上,二分答案去判断。因为答案具有单调性,所以二分可以。不知道是我写的哪里有问题,在牛客上加上快读,开40倍空间,用c++11交才过了。。
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=1e5+100;
struct node{
int l;
int r;
int num;
}p[maxx*40];
int a[maxx],root[maxx];
int n,m,tot;
/*-----------事前准备----------*/
inline int read()
{
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
/*------------主席树------------*/
inline int build(int l,int r)
{
int cur=++tot;
p[cur].num=0;
if(l==r) return cur;
int mid=l+r>>1;
p[cur].l=build(l,mid);
p[cur].r=build(mid+1,r);
return cur;
}
inline int update(int rot,int pos,int l,int r)
{
int cur=++tot;
p[cur]=p[rot];
p[cur].num++;
if(l==r) return cur;
int mid=l+r>>1;
if(pos<=mid) p[cur].l=update(p[rot].l,pos,l,mid);
else p[cur].r=update(p[rot].r,pos,mid+1,r);
return cur;
}
inline int query(int lrot,int rrot,int l,int r,int pos)
{
if(l>=pos) return p[rrot].num-p[lrot].num;
int mid=l+r>>1;
if(pos>mid) return query(p[lrot].r,p[rrot].r,mid+1,r,pos);
else return query(p[lrot].l,p[rrot].l,l,mid,pos)+(p[p[rrot].r].num-p[p[lrot].r].num);
}
int main()
{
int x,y;
while(~scanf("%d%d",&n,&m))
{
tot=0;
for(int i=1;i<=n;i++) a[i]=read();
root[0]=build(1,n);
for(int i=1;i<=n;i++) root[i]=update(root[i-1],a[i],1,n);
while(m--)
{
x=read(),y=read();
int l=1,r=n,mid,ans=0;
while(l<=r)
{
mid=l+r>>1;
if(query(root[x-1],root[y],1,n,mid)>=mid)
{
l=mid+1;
ans=mid;
}
else r=mid-1;
}
printf("%d\n",ans);
}
}
return 0;
}
努力加油a啊,(o)/~