CF840D Destiny (可持久化线段树、模板有重大问题)

题意:

有的疯狂的二次元爱好者,家里会有很多手办,这不就有一个,他家里有3e5个手办,他的手办按作品出现的先后次序给编了号,同一作品的手办使用了相同数字,然后他取出n个随便放成一排,现在他就来考你了,让你求出从编号l到编号r之间,哪个作品的手办出现次数,超过 (r-l+1)/k次,当然可能有不止一部作品满足,要找出最早的一部作品的编号(即最小编号)

题解:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
int n,m,q;
int a[maxn];//原始数组 
int t[maxn];//离散化数组
int T[maxn];//第i棵线段树的根节点编号
int lson[maxn*30];//每个节点的左儿子编号
int rson[maxn*30];//每个节点的右儿子编号
int c[maxn*30];//节点的权值
int tot;//动态开点 
void init_hash () {
    //事先离散化
    for (int i=1;i<=n;i++) t[i]=a[i];
    sort(t+1,t+n+1);
    m=unique(t+1,t+n+1)-t-1; 
} 
int Hash (int x) {
    return lower_bound(t+1,t+m+1,x)-t;
} 
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 up (int root,int p,int v) {
    int newRoot=tot++;
    int tmp=newRoot;
    int l=1,r=n;
    c[newRoot]=c[root]+v;
    while (l<r) {
        int mid=(l+r)>>1;
        if (p<=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]+v;
    }
    return tmp;
}
int query (int left_root,int right_root,int l,int r,int k) {
    if (c[left_root]-c[right_root]<=k) return -1;
    if (l==r) return l;
    int mid=(l+r)>>1;
    int ans=query(lson[left_root],lson[right_root],l,mid,k);
    if (ans==-1) ans=query(rson[left_root],rson[right_root],mid+1,r,k);
    return ans;
}
int main () {
    tot=0;
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;i++) scanf("%d",a+i);
    T[n+1]=build(1,n);
    for (int i=n;i;i--) {
        int p=a[i];
        T[i]=up(T[i+1],p,1);
    }
    //printf("%d\n",c[T[1]]);
    while (q--){
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",query(T[l],T[r+1],1,n,(r-l+1)/k));
    }
}

 

posted @ 2020-11-11 21:28  zlc0405  阅读(57)  评论(0编辑  收藏  举报