• set so 就


       

    问题 B: 就

    时间限制: 1 Sec  内存限制: 512 MB

    题目描述

    就so.in/.out

    【背景描述】

    一排 N 个数, 第 i 个数是 Ai , 你要找出 K 个不相邻的数, 使得他们的和最大。

    请求出这个最大和。

    【输入格式】

    第一行两个整数 N 和 K。

    接下来一行 N 个整数, 第 i 个整数表示 Ai 。

    【输出格式】

    一行一个整数表示最大和, 请注意答案可能会超过 int 范围

    【样例输入】

    3 2

    4 5 3

    【样例输出】

    7

    【数据范围】

    对于 20% 的数据, N, K ≤ 20 。

    对于 40% 的数据, N, K ≤ 1000 。

    对于 60% 的数据, N, K ≤ 10000 。

    对于 100% 的数据, N, K ≤ 100000 , 1 ≤ Ai ≤ 1000000000。

       考试时大部分人应该都自豪的写出了n*n的DP,能A60分,结果正解是贪心。对,就是贪心,最先选择最大的一个点,明显这不一定是最优解,而且他周围的两个点都没办法选了,而他的值加进了ans无法再踢除。。

       这些问题用一个set+链表就解决了。选了一个点,就把他周围两个点用链表缩成一个,权值赋成左边点权值+右边点权值-自己权值。这个就是用来反悔的。如果选了新的点,相当于向ans里加了A+C-B,而原来ans里加了B,B抵消了,

        就相当于没加。

       

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<set>
    #define ll long long
    #define N 100005
    #define inf 1000000000
    using namespace std;
    ll read()
    {
    	ll sum=0,f=1;char x=getchar();
    	while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    	while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();}
    	return sum*f;
    }
    struct hh
    {
    	int id;
    	ll h;
    	hh(){}
    	hh(int a,ll b)
    	{
    		h=b;
    		id=a;
    	}
        friend bool operator <(const hh &a,const hh &b)
        {
        	return (a.h!=b.h) ? (a.h>b.h):(a.id<b.id);
    	}
    };
    set<hh> st;
    int nex[N],fro[N],n,k;
    ll ans=0,a[N];  
    int main()
    {
    	freopen("so.in","r",stdin);
    	freopen("so.out","w",stdout);
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<=n;i++)
    	{
    	   scanf("%lld",&a[i]);
    	   nex[i]=i+1;
    	   fro[i]=i-1;	
    	   st.insert(hh(i,a[i]));
    	}a[0]=-1e15;
    	nex[n]=0;
        while(k--)
    	{
    		int x=st.begin()->id;
    		ans+=a[x];
    		a[x]=-a[x];
    		a[x]+=a[fro[x]];
    		a[x]+=a[nex[x]];
    		st.erase(st.begin());
    		st.erase(hh(nex[x],a[nex[x]]));
    		st.erase(hh(fro[x],a[fro[x]]));
    		st.insert(hh(x,a[x]));
    		if(fro[fro[x]])nex[fro[fro[x]]]=x;
    		if(nex[nex[x]])fro[nex[nex[x]]]=x;
    		nex[x]=nex[nex[x]];
    		fro[x]=fro[fro[x]];
    	} 
    	cout<<ans;
    }

  • 相关阅读:
    易耗品管理 第三四表 查询的存储过程
    [zz]使用vc编译libsvm
    程序调试小bug
    Ubuntu下安装配置OpenNI, OpenCV
    关于Linux下使用OpenCv读取视频打不开的问题
    jQuery实现图片点击放大
    关于 QtDBus 的种种
    javascript计时器的实现
    [QT]没有选择Debug构建方式.为文件的某行设置断点可能会失败
    linux firefox 不显示英文的解决
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632736.html
Copyright © 2020-2023  润新知