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。
人傻自带大常数
考试的时候想的是DP,明明是n^2的,在本机也能跑60分但是,多加了以为自己买不买的状态,其实并没有什么卵用,因为最优解的话根本不用考虑那个,结果滚动数组被卡
之后改题的时候傻傻的用了一个垃圾堆,边界处理起来贼麻烦,改了一个多小时,后来改用了set,但是又忘记考虑0和n+1两个边界如果不初始化成负无穷的话,会对答案造成影响,w了两个点又了好半天
这道题的总体思路就是贪心,每次选择最大的,然后把左右两个相邻的点与该点合成一个块压入set,若当前算的是5,那么再选就是舍弃5,选4,6,若在进行一次这样的操作就是舍弃4,6,选3,5,7;这样操作m次就能得到答案;
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 # define maxn 100010 10 using namespace std; 11 typedef long long LL; 12 int n,m; 13 struct node { 14 LL num; 15 int id; 16 node(){ 17 num=0; id=0; 18 } 19 }g[maxn]; 20 bool vis[maxn]; 21 int pre[maxn],nxt[maxn]; 22 bool operator < (node a,node b){ 23 return a.num>b.num; 24 } 25 bool operator == (node a,node b){ 26 return (a.num==b.num && a.id==b.id); 27 } 28 int main(){ 29 //freopen("so.in","r",stdin); 30 //freopen("so.out","w",stdout); 31 scanf("%d%d",&n,&m); 32 set<node> q; 33 for(int i=1;i<=n;i++){ 34 scanf("%lld",&g[i].num); 35 g[i].id=i; 36 q.insert(g[i]); 37 } 38 for(int i=1;i<=n;i++){ 39 pre[i]=i-1; 40 } 41 g[0].num=-0x7fffffff; 42 g[n+1].num=-0x7fffffff; 43 for(int i=n;i>=1;i--){ 44 nxt[i]=i+1; 45 } 46 LL ans=0; 47 node k;int u,v,x,y; 48 for(int i=1;i<=m;i++){ 49 k=*q.begin(); 50 //cout<<"k.id== "<<k.id<<" "<<k.num<<endl; 51 ans+=k.num; 52 int u=pre[k.id],v=nxt[k.id]; 53 54 q.erase(g[u]); q.erase(g[v]); 55 q.erase(g[k.id]); 56 x=pre[u]; y=nxt[v]; 57 nxt[x]=k.id; nxt[k.id]=y; 58 pre[y]=k.id; pre[k.id]=x; 59 g[k.id].num=g[v].num+g[u].num-g[k.id].num; 60 q.insert(g[k.id]); 61 } 62 cout<<ans<<endl; 63 return 0; 64 }