题意:找到序列中大于某个数ans的总个数sum,并且sum>=ans的最大的ans。
题解:简单修改主席树,然后秒过。
#include<bits/stdc++.h>
#define lson l,m
#define rson m+1,r
using namespace std;
const int maxn=100005;
struct Node {
int l,r,sum;
} p[3000010]; //毕竟有100000颗线段树。
int T[maxn],a[maxn],Hash[maxn],cnt=0;
int build(int l,int r) {
int rt=(++cnt);
if(l==r) {
return p[rt].sum=0;
}
int m=(l+r)>>1;
p[rt].l=build(lson);//注意这里的左右子树不在通过计算得到
p[rt].r=build(rson);//因为多棵线段树的左右节点掺杂,不存在原来线段树的计算规律。
return rt;
}
int update(int pre,int l,int r,int x) {
int rt=(++cnt);//rt为新加的一条树链的节点
p[rt].sum=p[pre].sum+1;
p[rt].l=p[pre].l;
p[rt].r=p[pre].r;
if(l==r)return rt;
int m=(l+r)>>1;
if(x<=m)p[rt].l=update(p[pre].l,lson,x);
else p[rt].r=update(p[pre].r,rson,x);
return rt;
}
int query(int u,int v,int l,int r,int k) {//注意这里的k不是第k大,而是右子树的数字总和。
if(l==r) {
return l;
}
int m=(l+r)>>1;
int num=p[p[v].r].sum-p[p[u].r].sum+k;
if(num<=m)return query(p[u].l,p[v].l,lson,num);//右边的数一定大于左边
else return query(p[u].r,p[v].r,rson,k);//父亲的右儿子一定比自己大
}
int main() {
int t;
int n,m;
while(scanf("%d%d",&n,&m)!=EOF) {
cnt=0;
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
Hash[i]=a[i];
}
T[0]=build(1,n);
for(int i=1; i<=n; i++) {
T[i]=update(T[i-1],1,n,a[i]);
}
while(m--) {
int l,r,k;
scanf("%d%d",&l,&r);
int x=query(T[l-1],T[r],1,n,0);
printf("%d\n",x);
}
}
return 0;
}
//不用结构体的模板
#include<bits/stdc++.h>
#define lson l, m
#define rson m+1, r
using namespace std;
const int N=1e5+5;
int L[N<<5], R[N<<5], sum[N<<5];
int tot;
int a[N], T[N], Hash[N];
int build(int l, int r)
{
int rt=(++tot);
sum[rt]=0;
if(l<r)
{
int m=(l+r)>>1;
L[rt]=build(lson);
R[rt]=build(rson);
}
return rt;
}
int update(int pre, int l, int r, int x)
{
int rt=(++tot);
L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+1;
if(l<r)
{
int m=(l+r)>>1;
if(x<=m)
L[rt]=update(L[pre], lson, x);
else
R[rt]=update(R[pre], rson, x);
}
return rt;
}
int query(int u, int v, int l, int r, int k)
{
if(l>=r)
return l;
int m=(l+r)>>1;
int num=sum[R[v]]-sum[R[u]]+k;
if(num<=m)
return query(L[u], L[v], lson, num);
else
return query(R[u], R[v], rson, k);
}
int main()
{
int t;
int n, m;
while(scanf("%d%d", &n, &m)!=EOF)
{
tot=0;
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
Hash[i]=a[i];
}
//sort(Hash+1, Hash+n+1);
//int d=unique(Hash+1, Hash+n+1)-Hash-1;
T[0]=build(1, n);
for(int i=1; i<=n; i++)
{
// int x=lower_bound(Hash+1, Hash+d+1, a[i])-Hash;
T[i]=update(T[i-1], 1, n, a[i]);
}
while(m--)
{
int l, r, k;
scanf("%d%d", &l, &r);
int x=query(T[l-1], T[r], 1, n, 0);
printf("%d\n", x);
}
}
}