zoukankan      html  css  js  c++  java
  • 蚯蚓

    蚯蚓

    给出一个大小为n集合({a_i}),每次操作选择集合中最大的元素(a_i),将其从集合中删除,然后集合中所有的元素值加上q,再向集合中加入元素([pa_i])(a_i-[pa_i]),显然p,q已经给出,给出m,t,询问第(t,2t,...,[m/t])次操作前中集合中最大的元素,并且输出所有操作完以后集合中第(t,2t,...,[(n+m)/t])大的元素。

    (1≤n≤10^5,0≤ai≤10^8,0<p<1,0≤q≤200)
    (0≤m≤7 imes 10^6,1≤t≤71)

    法一:优先队列

    注意到集合中每次要选出最大的元素,可以考虑优先队列维护,弹出队首(a_i),然后将其变成元素([pa_i])(a_i-[pa_i])加入优先队列,按照题目条件每次输出队首即可。

    至于集合中的每个元素都增加一个q,全局中开一个变量保存增加的值(不能理解没关系,具体实现看代码)。

    而最后的时候不停地弹出队首,这是第几次弹出队首,队首就是第几大元素,按照指定的要求输出第k大的元素。

    最终时间复杂度((n+m)log(n+m)),超时。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <functional>
    #define il inline
    #define ri register
    #define lb double
    using namespace std;
    priority_queue<int,vector<int>,less<int> >Q;
    void pen(int);
    il void read(int&);
    int main(){
        int n,m,q,u,v,t;lb p;
        read(n),read(m),read(q),
            read(u),read(v),read(t);p=(lb)u/v;
        ri int i,j,gzy(0);for(i=1;i<=n;++i)read(j),Q.push(j);
        for(i=1;i<=m;++i){j=Q.top()+gzy,Q.pop();
            if(!(i%t))pen(j),putchar(' ');gzy+=q;
            Q.push((int)(j*p)-gzy),Q.push(j-(int)(j*p)-gzy);
        }putchar('
    ');
        for(i=1;i<=n+m;++i){
            if(!(i%t))pen(Q.top()+gzy),putchar(' ');Q.pop();
        }
        return 0;
    }
    void pen(int x){
        if(x>9)pen(x/10);putchar(x%10+48);
    }
    il void read(int &x){
        x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    

    法二:单调性+归并排序

    一个很隐晦的性质,也许猜问题具有单调性会得到,某次操作下,设集合中两个元素(a_igeq a_j),此时(a_i)被选出用于操作变为元素(pa_i,(1-p)a_i),经过(t')次操作后,如果这两个元素没有被操作,将变为(pa_i+qt',(1-p)a_i+qt'),如果恰好(j)被操作了,那么就会分成两个元素(p(a_j+t'q)=pa_j+pt'q,(1-p)(a_j+t'q)=(1-p)a_j+(1-p)tq'),因为(a_igeq a_j,pin(0,1),1-pin(0,1)),得到

    [p(a_j+t'q)leq pa_i+qt' ]

    [(1-p)(a_j+t'q)leq (1-p)a_i+qt' ]

    于是对于操作分出的元素,按照其在操作前的元素大小,本身具有单调性,如果没理解这句话,继续后看。

    于是我们维护3个队列,第1个队列存储初始的集合,但是要从大到小排序,第二个队列存储每次操作(假设操作的是(a_i))产生(pa_i),而第三个队列存储((1-p)a_i),在当前操作的集合中,后面的被操作的元素,肯定小于等于当前被操作的元素,根据性质所分出来的两个元素乘以(p)的会单调递减,乘以(1-p)会单调递减,于是只要分别把其入应该入的队列,就可以保证这个队列的单调性,于是三个队列都能保证其单调递减,因此只要取各自的队首就可以知道当前操作下集合中最大的元素。

    对于最后的询问,因为三个队列都是有序的,显然多个有序的数列排序,考虑归并,最终可以做到时间复杂度(O(n+m))

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <functional>
    #define il inline
    #define ri register
    #define Size 7200000
    using namespace std;
    int T[3][Size],L[3],R[3],
        te[Size],tt;
    il void read(int&);
    int main(){int n,m,q,u,v,t;ri int gzy(0);
        ri double p;read(n),read(m),read(q);
        read(u),read(v),read(t),p=(double)u/v;
        for(int i(1);i<=n;++i)read(T[0][i]);
        sort(T[0]+1,T[0]+n+1,greater<int>());
        L[0]=1,R[0]=n,L[1]=L[2]=1;
        for(ri int i(1),j,k;i<=m;++i){j^=j;
            if(T[1][L[1]]>T[j][L[j]]||L[0]>R[0])j=1;
            if(T[2][L[2]]>T[j][L[j]])j=2;
            k=T[j][L[j]++]+gzy,gzy+=q;
            T[1][++R[1]]=(int)(k*p)-gzy;
            T[2][++R[2]]=k-(int)(k*p)-gzy;
            if(!(i%t))printf("%d ",k);
        }putchar('
    ');
        while(L[0]<=R[0]&&L[1]<=R[1])
            if(T[0][L[0]]>T[1][L[1]])te[++tt]=T[0][L[0]++];
            else te[++tt]=T[1][L[1]++];
        while(L[0]<=R[0])te[++tt]=T[0][L[0]++];
        while(L[1]<=R[1])te[++tt]=T[1][L[1]++];
        L[0]=1,R[0]=tt,R[1]=0;
        while(L[0]<=R[0]&&L[2]<=R[2])
            if(te[L[0]]>T[2][L[2]])T[1][++R[1]]=te[L[0]++];
            else T[1][++R[1]]=T[2][L[2]++];
        while(L[0]<=R[0])T[1][++R[1]]=te[L[0]++];
        while(L[2]<=R[2])T[1][++R[1]]=T[2][L[2]++];
        for(ri int i(1);i<=R[1];++i)
            if(!(i%t))printf("%d ",T[1][i]+gzy);
        return 0;
    }
    il void read(int &x){
        x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    
  • 相关阅读:
    法里数列
    母函数笔记
    贝尔数的指数母函数推导
    jQuery监听文本框值改变触发事件(propertychange)
    java-->TreeMap的使用
    查找-->二分查找和插值查找java实现
    查找-->斐波那契查找算法
    排序-->归并排序
    希尔排序(交换法和位移法)
    8皇后算法的简单实现(回溯)
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11236528.html
Copyright © 2011-2022 走看看