• bzoj 3524 可持久化线段树


      我们可以先离散化,然后建立权值的可持久化线段树,记录每个数出现的次数,对于区间询问直接判断左右儿子的cnt是不是大于(r-k+1)/2,然后递归到最后一层要是还是大于就有,否则不存在。

      反思:挺简单一道题调了一个晚上加一个几节课= =,原因是这道题的空间给的是128MB,那么就会有比较严重的卡空间的地方,开始我的线段树是记录的左右儿子和代表的区间,这样会MLE,那么我们可以不记录代表的区间然后递归的时候传上去区间也可以起到同样的效果。

    /**************************************************************
        Problem: 3524
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:7392 ms
        Memory:125808 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 500010
     
    using namespace std;
     
    struct segment {
        int cnt;
        int son[2];
        segment() {
            cnt=0;
            memset(son,0,sizeof son);
        }
    }t[10000000];
     
    struct rec {
        int num,key;
    }a[maxn];
     
    int n,m,tot;
    int rot[maxn],ans[maxn];
     
    bool cmp1(rec x,rec y) {
        return x.key<y.key;
    }
     
    bool cmp2(rec x,rec y) {
        return x.num<y.num;
    }
     
    void build(int &x,int l,int r) {
        if (!x) x=++tot;
        if (l==r) return ;
        int mid=l+r>>1;
        build(t[x].son[0],l,mid); build(t[x].son[1],mid+1,r);
        return ;
    }
     
    void insert(int &x,int rot,int key,int l,int r) {
        if (!x) x=++tot;
        if (l==r) {
            t[x].cnt=t[rot].cnt+1; return ;
        }
        int mid=l+r>>1;
        if (key>mid) {
            t[x].son[0]=t[rot].son[0];
            insert(t[x].son[1],t[rot].son[1],key,mid+1,r);
        } else {
            t[x].son[1]=t[rot].son[1];
            insert(t[x].son[0],t[rot].son[0],key,l,mid);
        }
        t[x].cnt=t[rot].cnt+1;
        return ;
    }
     
    int query(int lx,int rx,int key,int l,int r) {
        //printf("%d %d %d
    ",lx,rx,key);
        if (l==r) return l;
        int mid=l+r>>1;
        if (t[t[rx].son[0]].cnt-t[t[lx].son[0]].cnt>key) return query(t[lx].son[0],t[rx].son[0],key,l,mid); else
        if (t[t[rx].son[1]].cnt-t[t[lx].son[1]].cnt>key) return query(t[lx].son[1],t[rx].son[1],key,mid+1,r); else
            return 0;
    }
     
    int main() {
        //freopen("kur.in","r",stdin); freopen("kur.out","w",stdout);
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i].key),a[i].num=i;
        sort(a+1,a+1+n,cmp1);
        int j=1; ans[1]=a[1].key;
        for (int i=1,cur=a[1].key;i<=n;i++)
            if (a[i].key==cur) a[i].key=j; else cur=a[i].key,a[i].key=++j,ans[j]=cur;
        //for (int i=1;i<=n;i++) printf("%d %d
    ",a[i].num,a[i].key);
        sort(a+1,a+1+n,cmp2);
        build(rot[0],1,j);
        for (int i=1;i<=n;i++) insert(rot[i],rot[i-1],a[i].key,1,j);
        //for (int i=1;i<=tot;i++) printf("%d %d %d %d %d %d
    ",i,t[i].left,t[i].right,t[i].son[0],t[i].son[1],t[i].cnt);
        while (m--) {
            int l,r; scanf("%d%d",&l,&r);
            if (l>r) swap(l,r);
            printf("%d
    ",ans[query(rot[l-1],rot[r],(r-l+1)/2,1,j)]);
        }
        //fclose(stdin); fclose(stdout);
        return 0;
    }

    学长给了一个随机算法,虽然参数改了不是T就是WA,还是觉得挺有纪念意义的= =。

    //By BLADEVIL
    #include <ctime>
    #include <cstdio>
    #include <vector>
    #include <cstdlib>
    #define maxn 500010
    #define k 10
    
    using namespace std;
    
    int n,m;
    int a[maxn];
    vector<int>rot[maxn];
    
    int calc(int x,int y) {
        int l=0,r=rot[x].size()-1;
        int ans=0;
        while (l<=r) {
            int mid=l+r>>1;
            //printf("%d %d %d
    ",l,r,mid);
            if (rot[x][mid]<=y) ans=mid,l=mid+1; else r=mid-1;
        }
        return ans;
    }
    
    int judge(int x,int l,int r) {
        int a1=calc(x,l),a2=calc(x,r);
        int ans=a2-a1+1;
        if (rot[x][a1]!=l) ans--;
        return ans;
    }
    
    int main() {
        //freopen("kur.in","r",stdin); freopen("kur.out","w",stdout);
        srand((int)time(NULL));
        /*
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=1;i<=n;i++) rot[1].push_back(a[i]);
        scanf("%d",&m);
        printf("%d
    ",calc(1,m));
        return 0;
        */
        scanf("%d%d",&n,&m); 
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=1;i<=n;i++) rot[a[i]].push_back(i);
        while (m--) {
            int l,r; scanf("%d%d",&l,&r);
            for (int i=1;i<=k;i++) {
                int cur=l+rand()%(r-l+1);
                if (judge(a[cur],l,r)>(r-l+1)/2) {
                    printf("%d
    ",a[cur]); l=r=-1;
                    break;
                }
            }
            if (l!=-1) printf("0
    ");
        }
        fclose(stdin); fclose(stdout);
        return 0;
    }
  • 相关阅读:
    数据库简介
    计算机网络OSI七层协议
    信息论知识点(绪论)
    Wireshark抓取HTTP数据包
    配置FileZilla FTP服务器
    Redis集群搭建的几种方式
    Redis单个分片高可用&哨兵集群
    Redis哈希一致性&对应API操作
    MapReduce实现好友推荐
    window下使用IDEA远程调试伪分布式hadoop集群
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3670758.html
Copyright © 2020-2023  润新知