就(so) 题解
就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。
solution:
这题考试打的dp,本来有60结果手贱细节崩了瞬间少了55,~~~~(>_<)~~~~,用一个堆维护所有位置,每次取出最大的,然后把这个位置和两边的位置合并,选择合并之后的位置就相当于取消选择原来的位置,并选择两边的位置再把原来的和两边的在堆里删掉,再把合并之后的加入堆里可以用链表来维护两边的位置,重复K次即可,因为只需要k个数
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<set> 6 using namespace std; 7 #define inf ((long long)1<<62) 8 #define int long long 9 int read() { 10 int s=0,f=1; 11 char ch=getchar(); 12 while(ch>'9'||ch<'0') { 13 if(ch=='-') { 14 f=-1; 15 } 16 ch=getchar(); 17 } 18 while(ch>='0'&&ch<='9') { 19 s=(s<<1)+(s<<3)+(ch^48); 20 ch=getchar(); 21 } 22 return s*f; 23 } 24 struct node { 25 int ord,num; 26 friend bool operator < (node a,node b) { 27 return (a.num==b.num)?(a.ord>b.ord):(a.num>b.num); 28 } 29 }; 30 set <node> qq; 31 int pre[100005],nxt[100005],n,k,val[100005]; 32 signed main() { 33 n=read(); 34 k=read(); 35 for(int i=1,x; i<=n; i++) { 36 x=read(); 37 val[i]=x; 38 pre[i]=i-1; 39 nxt[i]=i+1; 40 qq.insert((node) { 41 i,x 42 }); 43 } 44 long long ans=0; 45 val[0]=-inf; 46 nxt[n]=0; 47 while(k--) { 48 int i=qq.begin()->ord; 49 qq.erase((node) { 50 i,val[i] 51 }); 52 ans+=val[i]; 53 val[i]=-val[i]; 54 val[i]+=val[pre[i]]+val[nxt[i]]; 55 qq.erase((node) { 56 pre[i],val[pre[i]] 57 }); 58 qq.erase((node) { 59 nxt[i],val[nxt[i]] 60 }); 61 qq.insert((node) { 62 i,val[i] 63 }); 64 if(pre[pre[i]]) { 65 nxt[pre[pre[i]]]=i; 66 } 67 if(nxt[nxt[i]]<=n) { 68 pre[nxt[nxt[i]]]=i; 69 } 70 pre[i]=pre[pre[i]]; 71 nxt[i]=nxt[nxt[i]]; 72 } 73 cout<<ans; 74 return 0; 75 }