zoukankan      html  css  js  c++  java
  • BZOJ2288:[POJ Challenge]生日礼物

    浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html

    题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2288

    首先我们可以把同符号的全部合成一个数,第一个如果是负数就扔了,最后一个也是。

    然后把所有的正数都加起来,记段数为(x),若(x<=m)则这就是正确答案,否则我们需要使用一些手段让(x)降低为(m)。比如扔掉某些权值很小的正整数,或者加上某些绝对值很小的负数,这样都会使(x--)。但是如果我同时扔掉某个权值很小的正整数又加上这个数两边的负数显然是很蠢的,又或者我加上了某个绝对值很小的负数又扔掉这个负数两边的正数,显然也是很蠢的。

    于是,我们往堆里扔所有数的绝对值,做一遍数据备份,不过每次是减去堆顶的值就行了。

    时间复杂度:(O(nlogn))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn=1e5+5;
    
    int a[maxn];
    int n,m,ans,cnt;
    
    int read() {
    	int x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
    
    struct Linked_List {
        int lst,nxt,val,in_heap;
    
        Linked_List() {}
    
        Linked_List(int _lst,int _nxt,int _val) {
            lst=_lst,nxt=_nxt,val=_val;
        }
    }L[maxn];
    
    struct Heap {
        int tot;
        int tree[maxn];
    
        bool less(int id1,int id2) {return L[id1].val<L[id2].val;}
    
        void up(int pos) {
            while(pos>1) {
                if(less(tree[pos],tree[pos>>1])) {
                    swap(tree[pos],tree[pos>>1]);
                    swap(L[tree[pos]].in_heap,L[tree[pos>>1]].in_heap);
                    pos>>=1;
                }
                else break;
            }
        }
    
        void down(int pos) {
            int son=pos<<1;
            while(son<=tot) {
                if(son<tot&&less(tree[son|1],tree[son]))son|=1;
                if(less(tree[son],tree[pos])) {
                    swap(tree[son],tree[pos]);
                    swap(L[tree[son]].in_heap,L[tree[pos]].in_heap);
                    pos=son,son=pos<<1;
                }
                else break;
            }
        }
    
        void ins(int v) {tree[++tot]=v,L[v].in_heap=tot,up(tot);}
    
        int pop() {
            int res=tree[1];
            tree[1]=tree[tot--];
            L[tree[1]].in_heap=1;
            down(1);return res;
        }
    
        void del(int id) {
            if(id==tot) {tot--;return;}
            tree[id]=tree[tot--];
            L[tree[id]].in_heap=id;
            if(id==1)down(id);
            else if(id==tot)up(id);
            else up(id),down(id);
        }
    }T;
    
    void work() {
    	for(int i=1;i<=n;i+=2)
    		ans+=a[i],m--;
    	for(int i=1;i<=n;i++) {
    		L[i]=Linked_List(i-1,i+1,abs(a[i]));
    		T.ins(i);
        }
        while(m<0) {
            int id=T.pop(),lst=L[id].lst,nxt=L[id].nxt;ans-=L[id].val;
            if(!lst) {
                T.del(L[nxt].in_heap);m++;
                L[L[nxt].nxt].lst=0;continue;
            }
            if(nxt==n+1) {
                T.del(L[lst].in_heap);m++;
                L[L[lst].lst].nxt=n+1;continue;
            }
            T.del(L[lst].in_heap),T.del(L[nxt].in_heap);
            L[lst].val=L[lst].val+L[nxt].val-L[id].val;T.ins(lst);
            L[lst].nxt=L[nxt].nxt,L[L[nxt].nxt].lst=lst;m++;
        }
        printf("%d
    ",ans);
    }
    
    int main() {
    	n=read(),m=read();
    	if(!m) {puts("0");return 0;}
    	for(int i=1;i<=n;i++) {
    		int x=read();
    		if(!x)continue;
    		if(!cnt&&x<0)continue;
    		if(!cnt)a[++cnt]=x;
    		else {
    			if((a[cnt]<0)==(x<0))a[cnt]+=x;
    			else a[++cnt]=x;
    		}
    	}
    	if(a[cnt]<0)cnt--;
    	n=cnt;work();
    }
    
  • 相关阅读:
    Java面试之最常见的十道面试题(超经典)
    hdu 3939(勾股+容斥)
    poj 1845 (逆元 + 约数和)
    hdu 5607 BestCoder Round #68 (矩阵快速幂)
    中国剩余定理
    Math
    (⊙o⊙)…
    lucas定理
    hdu 5600 BestCoder Round #67 (div.2)
    hdu5601 BestCoder Round #67 (div.2)
  • 原文地址:https://www.cnblogs.com/AKMer/p/10295481.html
Copyright © 2011-2022 走看看