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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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
#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<>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>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;
}

 

你可能感兴趣的:(ACM)