标签:des style blog class code java
7 1 1 2 3 4 4 5 3 1 2 3 0
7 10 12
/*分析:
dp[i]表示区间长度为i时的个数
则从区间长度i-1到i减少了最后一个i-1长度的区间
记last[i]表示最后一个区间长度为i的不同数的个数
所以dp[i]=dp[i-1]-last[i-1]
同时从区间i-1长度到i增加了n-i+1个数
增加的数为a[i],a[i+1],a[i+2]...a[n]
则增加的这些数表示区间长度为i且以a[i...n]结尾
有多少是不能增加的呢?
比如a[1]~a[i-1]存在a[i],以a[i]结尾的区间长度为i的区间就不用增加a[i]这个数
在这里预处理时以a[i]结尾的区间长度为l~r不能增加
则l=i-pos[a[i]]+1;//pos[a[i]]表示i位置前出现的a[i]
r=i-1+1+1
用树状数组能快速的累加
所以最终增加的是n-i+1-Query(i)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <cmath>
#include <iomanip>
#define INF 99999999
typedef __int64 LL;
using namespace std;
const int MAX=1000000+10;
int n,m;
int pos[MAX],a[MAX];
LL dp[MAX],last[MAX],c[MAX];
int lowbit(int x){
return x&(-x);
}
void Update(int x,int d){
while(x<=n){
c[x]+=d;
x+=lowbit(x);
}
}
LL Query(int x){
LL sum=0;
while(x>0){
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main(){
while(~scanf("%d",&n),n){
memset(pos,-1,sizeof pos);
memset(c,0,sizeof c);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
if(pos[a[i]] != -1){
Update(i-pos[a[i]]+1,1);
Update(i-1+2,-1);
}
pos[a[i]]=i;
}
memset(pos,-1,sizeof pos);
memset(last,0,sizeof last);//last记录最后面的长度为i的不同数的个数
for(int i=n;i>=1;--i){
last[n-i+1]=last[n-i];
if(pos[a[i]] == -1)++last[n-i+1];
pos[a[i]]=i;
}
dp[1]=n;
for(int i=2;i<=n;++i){
dp[i]=dp[i-1]+(n-i+1-Query(i))-last[i-1];
}
scanf("%d",&m);
for(int i=0;i<m;++i){
scanf("%d",&n);
printf("%I64d\n",dp[n]);
}
}
return 0;
}
hdu4455之树状数组+DP,布布扣,bubuko.com
标签:des style blog class code java
原文地址:http://blog.csdn.net/xingyeyongheng/article/details/25833549