• HDU 6180 Schedule


    最开始发现和之前听某个大佬讲的贪心很像,后来写了好几发都T了,甚至把原来的数组改成了VECTOR,后来发现似乎需要来一发二叉平衡树。。。

    此时,队友波塞冬堆出来了最后一题,成功签到,我把题拿给队友,队友表示。。。这不是线段树吗。。。

    于是下面是。。。赛中没整出来,但是赛后用自有“ 玄学树状数组 ”堆出来的题解。

    设定1,我们要求的东西是:最小的机器启动数量前提下,最小的机器运行时间。

    推论1,因而,在每个区间进行+1操作,之后统计最大的点的值即可

    推论2,最短运行时间应当有,最后启动的机器,运行到最后,可以得到的时间。例如样例有:
    1
    3
    1 3
    4 6
    2 5
    编号:1  2  3  4  5  6  7
    次数:1  2  2  2  1  0  0

    如上,在第第一小时,器一台机器启动,在第二小时,第二台机器启动,在第5小时,其中一台机器结束,在第六小时,两台机器都结束。

    于是,认为最后结束的应该是最后启动的机器,于是,将【2,6)之间所有数字减一:

    编号:1  2  3  4  5  6  7
    次数:1  1  1  1  0  0  0

    从而得到第二只机器运行时间为6-2(4小时)

    之后,发现,此时只有一台机器在运作,因而,关掉这台机器:

    编号:1  2  3  4  5  6  7
    次数:0  0  0  0  0  0  0

    第一台启动的机器运行时间为:5-1=4小时

    于是,总运行时间和为8小时,启动机器数量为2小时。

    AC代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    /*
    *常量MAXN用于设定树状数组的尺寸大小
    */
    const long long MAXN=300233;
    const long long INF=1e9+233;
    
    
    class TreeLikeArray
    {
        public:
    /*
    *数组c1用来储存A[i]-A[i-1];
    */
            long long c1[MAXN];
    /*
    *数组c2用来储存(A[i]-A[i-1])*(i-1);
    *或认为用于储存(i-1)*c1[i];
    *两种实现方式完全等价
    */
            long long c2[MAXN];
    /*
    *树状数组的常规操作,参数要求传入数组并指明更新位置,以及更新参数。
    *树状数组基础底层操作
    */
            void init()
            {
                memset(c1,0,sizeof(c1));
                memset(c2,0,sizeof(c2));
            }
            void add(long long array[],long long pos,long long key)
        {
            while(pos<MAXN)
            {
                array[pos]+=key;
                pos+=pos&(-pos);
            }
        }
    /*
    *特别树状数组单点更新操作,要求传入位置和参数
    */
        void add(long long pos,long long key)
        {
            add(c1,pos,key);
            add(c1,pos+1,-key);
            add(c2,pos,(pos-1)*key);
            add(c2,pos+1,-pos*key);
        }
    /*
    *特别树状数组多点更新操作,要求传入起始位置、终止位置和参数
    *该操作将会使得[pos1,pos2]闭区间内所有元素得到更新
    */
        void add(long long pos1,long long pos2,long long key)
        {
            add(c1,pos1,key);
            add(c1,pos2+1,-key);
            add(c2,pos1,(pos1-1)*key);
            add(c2,pos2+1,-pos2*key);
        }
    /*
    *树状数组的常规操作,参数要求传入数组并指明求和位置
    *树状数组基础底层操作
    */
        long long getSum(long long array[],long long pos)
        {
            long long ret=0;
            while(pos>0)
            {
                ret+=array[pos];
                pos-=pos&(-pos);
            }return ret;
        }
    /*
    *从起始节点到目标节点闭区间求和[0,i]
    */
        long long getSum(long long pos)
        {
            return pos*getSum(c1,pos)-getSum(c2,pos);
        }
    /*
    *求[pos1,pos2]闭区间内元素和
    */
        long long getSum(long long pos1,long long pos2)
        {
            return getSum(pos2)-getSum(pos1-1);
        }
    /*
    *求pos单个元素的值
    */
        long long getSingle(long long pos)
        {
            return getSum(pos,pos);
        }
    };TreeLikeArray t1;
    
    long long a[MAXN];
    long long b[MAXN];
    long long c[MAXN];    int n;
    long long mach[    MAXN];
    
    long long mapp(long long key)
    {
        return lower_bound(c,c+2*n,key)-c+1;
    }
    
    void init()
    {
    
    
        t1.init();
    //    memset(mach,0,sizeof(mach));
        cin>>n;
        for(int i=0;i<n;++i)
        {
            cin>>a[i]>>b[i];
            c[i*2]=a[i];
            c[i*2+1]=b[i];
            mach[i]=0;
        }
        sort(c,c+2*n+1);
        for(int i=0;i<n;++i)
        {
            int aa=mapp(a[i]);
            int bb=mapp(b[i]);
            t1.add(aa,bb-1,1);
        }
        long long maxx=0;
        for(int i=1;i<2*n+23;++i)
        {
            int key=t1.getSingle(i);
            if(key>maxx)mach[key]=i,maxx=key;
    //        cout<<key<<ends<<mach[key]<<endl;
        }
    //    cout<<maxx<<" ";
    
            long long mm=maxx;
        long long pos=2*n+233;
        long long ans=0;
        while(maxx)
        {
            while(t1.getSingle(pos)<=0)pos--;
    //        cout<<c[mach[maxx]-1]<<"  checkpoint "<<c[pos]<<endl;
            
            t1.add(mach[maxx],pos,-1);
            ans+=c[pos]-c[mach[maxx]-1];
            
            if(!mach[maxx-1])mach[maxx-1]=mach[maxx];
            maxx--;
        }
        cout<<mm<<" "<<ans<<"
    ";
        
        
    }
    
    int main()
    {
        cin.sync_with_stdio(false);
        int t;cin>>t;
        for(int it=0;it<t;++it)
        init();
    }
  • 相关阅读:
    总有一天你会爱上我
    你已把我的心带走
    创业提示】创业不能以赚多少钱为目标!
    创业测试:看看你身上成功的潜质
    迁芸(名字作诗)
    请你陪我一程
    智力型企业领导艺术
    方学萍(帮别人名字作诗)
    创业者身上一定要存在的几点修为
    以小博大:小本成功创业经验谈
  • 原文地址:https://www.cnblogs.com/rikka/p/7424882.html
Copyright © 2020-2023  润新知