题目大意:对于每个数而言,可以将其染成红或蓝,对于每一个数,定义其贡献为,当且仅当这个数最近的同色数与其相等,否则其贡献为0,求最大贡献和。
思路:考虑dp
1.考场20多分钟想的奇怪东西:
定义表示第i为的颜色为蓝或红,则有转移:
问题出在calc中,当时想的是就是他的值。但其实拿那个样例比对一下,就能发现,对于最左边的数,它的贡献是,其他点就是把相邻两个数的值相等的贡献加起来。注意到如果相邻两个相同数被染成同样的颜色,那么应该是(一定要拿特殊数据测一测,否则只有5pts)。
2.呼之欲出,维护前缀和表示前i位的calc值,那么
#include<bits/stdc++.h>using namespace std;const int N = 1e6 + 10;int f[N],n,a[N],ans;int calc(int st,int ed){int ans=f[st];if(st>ed&&st-1>=1) return f[st-1];if(st==ed) return f[st];for(int i=st+1;i<=ed;i++) ans+=(a[i]==a[i-1])*a[i]; return ans;
}
void solve(){memset(f,0,sizeof f);cin>>n;for(int i=1;i<=n;i++) cin>>a[i];for(int i=2;i<=n;i++){f[i]=f[i-1];int sum=0;for(int j=i-1;j>=1;j--){//if(a[i]!=a[j]) continue;int st=j+1,ed=i-1;//st+1 - edif(st>ed&&st-1>=1) f[i]=max(f[i],(a[i]==a[j])*a[i]+f[st-1]);else if(st==ed) f[i]=max(f[i],(a[i]==a[j])*a[i]+f[st]);else if(st<ed){sum+=(a[j+2]==a[j+1])*a[j+1];f[i]=max(f[i],(a[i]==a[j])*a[i]+sum+f[st]);} //f[i]=max(f[i],(a[i]==a[j])*a[i]+calc(j+1,i-1));}}cout<<f[n]<<endl;
}
int main(){int T;cin>>T;while(T--) solve();return 0;
}
考虑优化:很明显只有相等的值才能造成贡献
策略1.两位相邻,
策略2.两位之间差一位,
策略3.两位之间的格子超过两位,
其中t表示其中与其相同值的格子的位置。
直接分类是接近,考虑的单调性,可以知道这是单调递增的,每次以上次最后点为起点,是为下一个点的起点和这个点的终点即可。
复杂度,当然没看出单调性也可以套个线段树维护后面那个东西,本题不卡常。
#include<bits/stdc++.h>
#define int long long
using namespace std;const int N = 1e6 + 10;int f[N],n,a[N],ans,q[N],mx,g[N],maxn,lst[N];
vector<int> v[N];
void solve(){memset(f,0,sizeof f);memset(q,0,sizeof q);maxn=0;memset(g,0,sizeof g);memset(lst,0,sizeof lst); cin>>n;for(int i=1;i<=n;i++){cin>>a[i];maxn=max(maxn,a[i]);if(a[i]==a[i-1]) q[i]=a[i];q[i]+=q[i-1];v[a[i]].push_back(i);} for(int i=2;i<=n;i++){f[i]=f[i-1];int sum=0;f[i]=max(f[i],(a[i]==a[i-1])*a[i]+f[i-1]);if(i>2) f[i]=max(f[i],(a[i]==a[i-2])*a[i]+f[i-1]);for(int j=lst[a[i]];j<v[a[i]].size();j++){int t=v[a[i]][j];if(t>i-3){lst[a[i]]=j;break;} f[i]=max(f[i],a[i]+q[i-1]-q[t+1]+f[t+1]);}}cout<<f[n]<<endl;for(int i=1;i<=maxn;i++) v[i].clear();
}
signed main(){int T;cin>>T;while(T--) solve();return 0;
}
summary:自己的t2很蒙,搞到t3只有1个小时多一点,实际想这一题只有30-40分钟,没有自己仔细调一调,导致暴力dp都没有写出来。希望noip能自己写出一个正解dp出来