标签:int 贡献 maxn 端点 区间 计数问题 include
给你一个序列,每个数字有一个颜色,一个区间的贡献值是颜色的个数,颜色是1到n的整数表示,问这n*(n+1)/2个区间的贡献值的和是多少;n<=1e5;
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn=1e5+10; int n,a[maxn],pre[maxn]; typedef long long ll; ll sum,ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { sum+=i-pre[a[i]]; ans+=sum; pre[a[i]]=i; //cout<<sum<<" "<<ans<<" "<<pre[a[i]]<<endl; } printf("%lld",ans); return 0; }
o(n)枚举右端点,记录当前颜色上一次出现的位置,因为在上一次出现的前面那些数加上当前的一位贡献也不会更新,但是他们之间的数加上当前数一定都不重复,组成区间贡献值加一,
此时sum记录的是前一个为右端点时所有区间的贡献,所以加上的只有他们之间数的个数;
sum+上i-pre【a[i]】表示前面的区间右端点变成当前所有的贡献值,ans加上就好了;
实际上是一个递推过程,每次都计算的是以当前位置作为右节点,然后所有区间的贡献值,在计算总和的时候并不需要考虑加上前面其他不是当前点为右端点的区间
如果实在看不懂的话(我都有点蒙),还可以写成这样:
int main(){ //freopen("in.txt","r",stdin); read(n); for(int i=1;i<=n;i++)read(a[i]); for(int i=1;i<=n;i++)dp[i]=dp[i-1]+i-last[a[i]],last[a[i]]=i; for(int i=1;i<=n;i++)ans+=dp[i]; cout<<ans<<'\n'; return 0; }
标签:int,贡献,maxn,端点,区间,计数问题,include 来源: https://www.cnblogs.com/WHFF521/p/11519520.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。