1 条题解

  • 1
    @ 2019-01-08 21:02:40
    /*
    法一:运用优先队列简化代码
    法二:若不熟悉STL,这里提供了手写堆
    */
    #define method_1
    #ifdef method_1
    /*
    贪心
    首先简化序列 将正负数合并 例如 2 2 -1 -3 2 -4 1 1 变成4 -4 2 -4 2
    即变成正负数相间的形式
    这时计算出正数的数量 若其小于等于m 答案就是正数的和
    否则 就将其全部插入到优先队列里头(负数加绝对值之后插入)
    每次取出小根堆的堆顶 将其删去 同时更新答案 
    其中 删去正数表示这个联通块不选
    删去负数表示合并相邻两个联通块(若这个负数在两端 就直接删去 不更新答案)
    最后为了维护删除后的序列 需要用一个简化的双向链表  
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5;
    const int INF=0x3f3f3f3f;
    ll n,m,a[maxn],mark[maxn],cnt=0,temp=0,ans=0,l[maxn],r[maxn];
    priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;
    void del(int x){
        mark[x]=1;
        l[r[x]]=l[x];
        r[l[x]]=r[x];
    }
    int main() {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        ll x;
        for(int i=1;i<=n;i++){
            cin>>x;
            if(x!=0){
                if(a[temp]*x>0) a[temp]+=x;
                else a[++temp]=x;
            }
        }
        n=temp;
        for(int i=1;i<=n;i++){
            if(a[i]>0){
                cnt++;
                ans+=a[i];
            }
            l[i]=i-1;
            r[i]=i+1;
            q.push(make_pair(abs(a[i]),i));
        }
        while(cnt>m){
            while(mark[q.top().second]) q.pop();
            int x=q.top().second;
            q.pop();
            if((l[x]==0||r[x]==n+1)&&a[x]<0) del(x); //注意||的优先级低于&& 所以要有括号 
            else{
                ans-=abs(a[x]);
                cnt--;
                a[x]+=a[l[x]]+a[r[x]];
                q.push(make_pair(abs(a[x]),x));
                del(l[x]);
                del(r[x]);
            }
        }
        cout<<ans;
        return 0;
    }
    #endif
    #ifdef method_2
    /*
    
    */
    #include<iostream>
    #include<cstdio>
    using namespace std;
    int a[100010],b[100010],L[100010],R[100010],q[100010],v[100010];
    int n,m,t,p,ans,i,temp,x;
    
    void up(int p) {
        while(p>1)
            if(b[q[p]]<b[q[p>>1]]) {
                swap(q[p],q[p>>1]);
                swap(v[q[p]],v[q[p>>1]]);
                p>>=1;
            } else break;
    }
    
    void down(int l,int r) {
        int t=2*l;
        while(t<=r) {
            if(t<r&&b[q[t]]>b[q[t+1]]) t++;
            if(b[q[l]]>b[q[t]]) {
                swap(q[l],q[t]);
                swap(v[q[l]],v[q[t]]);
                l=t,t=2*l;
            } else break;
        }
    }
    
    void insert(int i) {
        q[++p]=i;
        v[i]=p;
        up(p);
    }
    void erase(int i) {
        v[q[p]]=v[i];
        q[v[i]]=q[p];
        p--;
        up(v[i]);
        down(v[i],p);
    }
    
    int main() {
        cin>>n>>t;
        for(i=1; i<=n; i++) scanf("%d",&a[i]);
        for(; n&&a[n]<=0; n--);
        for(i=1; i<=n&&a[i]<=0; i++);
        if(i>n) {
            puts("0");
            return 0;
        }
        for(; i<=n; i++)
            if(a[i]>0&&a[i-1]>0 || a[i]<=0&&a[i-1]<=0) b[m]+=a[i];
            else b[++m]=a[i];
        for(i=1; i<=m; i++)
            if(b[i]>0) temp++,ans+=b[i];
            else b[i]=-b[i];
        if(temp<=t) {
            cout<<ans<<endl;
            return 0;
        }
        for(i=1; i<=m; i++) {
            L[i]=i-1,R[i-1]=i;
            insert(i);
        }
        for(i=t; i<temp; i++) {
            ans-=b[x=q[1]];
            if(!L[x]) {
                erase(x),erase(R[x]);
                L[R[R[x]]]=0;
            } else if(!R[x]) {
                erase(x),erase(L[x]);
                R[L[L[x]]]=0;
            } else {
                erase(L[x]),erase(R[x]),erase(x);
                b[x]=b[L[x]]+b[R[x]]-b[x];
                insert(x);
                L[x]=L[L[x]],R[L[x]]=x;
                R[x]=R[R[x]],L[R[x]]=x;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    #endif
    
  • 1

信息

难度
7
分类
(无)
标签
(无)
递交数
55
已通过
9
通过率
16%
被复制
3
上传者