分析:
此题为一个环,告诉你环上的权值,求最大选择和;
选择要求:选了A,与A相邻的俩个元素就不能选。
数据 60% n=5000
100% n=200000
我65分dp
60% dp
dp[i][j]=max(dp[i-1][j],dp[i-2][j-1]+a[i]);
再多旋转几圈防止1和n冲突 复杂度O(N^2)
代码:
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
//#include<ctime>
using namespace std;
int n,m;
int a[5010];
int b[5010];
int dp[5010][5010];
int ans;
int read()
{
int k=0,f=1;
char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {k=k*10+(c-'0'); c=getchar();}
return k*f;
}
int main()
{
freopen("compile.in","r",stdin);
freopen("compile.out","w",stdout);
int i,j,k;
n=read();
m=read();
if(m>(n>>1)) {cout<<"Error!";return 0;}
for(i=1;i<=n;i++)
{
a[i]=read();
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++) dp[i][j]=-1000000000;
dp[1][1]=a[1];
dp[2][1]=max(a[1],a[2]);
for(i=3;i<=n;i++)
for(j=1;j<=min(m,(n+1)>>1);j++)
{
dp[i][j]=max(dp[i-2][j-1]+a[i],dp[i-1][j]);
}
ans=dp[n][m];
k=0;
for(i=n/3;i<=n;i++)
b[++k]=a[i];
for(i=1;i<n/3;i++)
b[++k]=a[i];
for(i=1;i<=n;i++) a[i]=b[i];
for(i=1;i<=n;i++)
for(j=1;j<=m;j++) dp[i][j]=-1000000000;
dp[1][1]=a[1];
dp[2][1]=max(a[1],a[2]);
for(i=3;i<=n;i++)
for(j=1;j<=min(m,(n+1)>>1);j++)
{
dp[i][j]=max(dp[i-2][j-1]+a[i],dp[i-1][j]);
}
ans=min(dp[n][m],ans);
k=0;
for(i=n/2+1;i<=n;i++)
b[++k]=a[i];
for(i=1;i<=n/2;i++)
b[++k]=a[i];
for(i=1;i<=n;i++) a[i]=b[i];
for(i=1;i<=n;i++)
for(j=1;j<=m;j++) dp[i][j]=-1000000000;
dp[1][1]=a[1];
dp[2][1]=max(a[1],a[2]);
for(i=3;i<=n;i++)
for(j=1;j<=min(m,(n+1)>>1);j++)
{
dp[i][j]=max(dp[i-2][j-1]+a[i],dp[i-1][j]);
}
ans=min(dp[n][m],ans);
cout<<ans;
return 0;
}
100%数据
利用网络流残余流量思想(并不懂)
建立大根堆,维护权值和映射
用了B,就废掉A,C,再加入A+C-B
若下一次选了A+C-B 则总和为A+C
实现过程用的queue
因为要修改左右元素是什么,而queue里面没有编号无法修改queue内的内容(例如迪杰斯特拉的手写堆是因为修改dis为queue内排序基准),
所以要用映射。
每个queue记录权值和映射,映射表示它在queue外普通int数组的编号,修改时直接修改int数组的值,queue内元素映射出来自然就是修改后的值了
左右元素用l,r储存(like dancing link)l[i]=l[l[i]],r[l[i]]=i........... ban判断是否废掉了(删点方法2333)
AC代码:
//queue内开映射
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <cstring>
#include <queue>
#include <string>
#define N 200100
#define INF (int)1e9
using namespace std;
struct node
{
int v;
int p; //映射
bool operator < (const node &a)const
{
return v<a.v;
}
};
priority_queue <node> q;
int n;
int m;
int a[N];
int l[N];
int r[N];
bool ban[N];
int ans;
int main ()
{
//freopen("cs.in","r",stdin);
//freopen("cs.out","w",stdout);
scanf("%d%d",&n,&m);
if(m>n/2)
{
printf("Error!\n");
return 0;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
l[i]=i-1;r[i]=i+1;
node t;
t.v=a[i];
t.p=i;
q.push(t);
}
l[1]=n;r[n]=1;
for(int i=1;i<=m;i++)
{
while(ban[q.top().p])q.pop();
int w=q.top().v;
int x=q.top().p;
q.pop();
ans+=w;
a[x]=a[l[x]]+a[r[x]]-a[x];
ban[l[x]]=ban[r[x]]=true;
l[x]=l[l[x]];r[x]=r[r[x]];
r[l[x]]=x;l[r[x]]=x;
node t;
t.v=a[x];
t.p=x;
q.push(t);
}
cout<<ans;
return 0;
}