HDU 6278 (可持续化线段树+二分)

题意:
h-index为 有h篇论文,引用数超过h 中最大的h。
给出n篇论文的论文引用次数,问如果只有[L,R]的论文的情况下,h-index是多少。

思路:
注意h-index的定义,如果要求[L,R]的h-index,对[L,R]的论文从小排序,令a[L+x]=y,说明有(R-L+1-x)篇论文的引用数大于y,注意到这个判断是单调的,所以可以二分找到满足条件最大的h=(R-L+1-x)。
但是每个区间排序复杂度太高,我们需要的二分信息可以通过可持续化线段树查询得到。

代码:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <sstream>
#define pb push_back
#define X first
#define Y second
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pii pair<int,int>
#define qclear(a) while(!a.empty())a.pop();
#define lowbit(x) (x&-x)
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define mst(a,b) memset(a,b,sizeof(a))
#define cout3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endl
#define cout2(x,y) cout<<x<<" "<<y<<endl
#define cout1(x) cout<<x<<endl
#define IOS std::ios::sync_with_stdio(false)
#define SRAND srand((unsigned int)(time(0)))
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
using namespace std;
const double PI=acos(-1.0);
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=100005;
const int maxm=3000005;

int n,q,m,tot;
int a[maxn], t[maxn];
int T[maxm], lson[maxm], rson[maxm], c[maxm];

void Init_hash() {
    for(int i = 1; i <= n; i++)
        t[i] = a[i];
    sort(t+1,t+1+n);
    m = unique(t+1,t+1+n)-t-1;
}
int build(int l,int r) {
    int root = tot++;
    c[root] = 0;
    if(l != r) {
        int mid = (l+r)>>1;
        lson[root] = build(l,mid);
        rson[root] = build(mid+1,r);
    }
    return root;
}
int tohash(int x) {
    return lower_bound(t+1,t+1+m,x) - t;
}
int update(int root,int pos,int val) {
    int newroot = tot++, tmp = newroot;
    c[newroot] = c[root] + val;
    int l = 1, r = m;
    while(l < r) {
        int mid = (l+r)>>1;
        if(pos <= mid) {
            lson[newroot] = tot++;
            rson[newroot] = rson[root];
            newroot = lson[newroot];
            root = lson[root];
            r = mid;
        } else {
            rson[newroot] = tot++;
            lson[newroot] = lson[root];
            newroot = rson[newroot];
            root = rson[root];
            l = mid+1;
        }
        c[newroot] = c[root] + val;
    }
    return tmp;
}
int query(int left_root,int right_root,int k) {
    int l = 1, r = m;
    while( l < r) {
        int mid = (l+r)>>1;
        if(c[lson[left_root]]-c[lson[right_root]] >= k ) {
            r = mid;
            left_root = lson[left_root];
            right_root = lson[right_root];
        } else {
            l = mid + 1;
            k -= c[lson[left_root]] - c[lson[right_root]];
            left_root = rson[left_root];
            right_root = rson[right_root];
        }
    }
    return l;
}
//mid表示paper的数量,now表示找到mid篇paper,需要查询第now小的数来确定引用数
bool check(int mid,int now,int ql,int qr){
    int pos=query(T[ql],T[qr+1],now);
    return t[pos]>=mid;
}
void solve() {
    while(~sdd(n,q)) {
        tot=0;
        for(int i=1; i<=n; i++) {
            sd(a[i]);
        }
        Init_hash();
        T[n+1] = build(1,m);
        for(int i = n; i ; i--) {
            int pos = tohash(a[i]);
            T[i] = update(T[i+1],pos,1);
        }
        for(int i=0; i<q; i++) {
            int ql,qr;
            sdd(ql,qr);
            int l,r,ans=1;
            l=1;
            r=qr-ql+1;
            //注意存在l==r
            while(l<=r) {
                int mid=(l+r)>>1;
                if(check(mid,(qr-ql+2-mid),ql,qr)) {
                    ans=mid;
                    l=mid+1;
                } else {
                    r=mid-1;
                }
            }
            printf("%d\n",ans);
        }
    }
    return ;
}
int main() {
#ifdef LOCAL
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
#else
    //    freopen("","r",stdin);
    //    freopen("","w",stdout);
#endif
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_38378637/article/details/81368021
今日推荐