//hdu 4455 貌似是dp吧,写完还要改名字;
//
//
//10^6 数,10^4查询
//防止tle
//
//维护一个最后位置,维护一个距离,扫一遍,来处理;
//防止mle
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define maxn 1001010
#define ll __int64
using namespace std;
int dis[maxn];
int ans[maxn];
int n;
int num[maxn];
int a[maxn];
int cnt[maxn];
bool visit[maxn];
///直接从大于的处理就不用考虑什么一定要从第i位开始的问题了。。。
//真是都比
//调了半天的数组大小,总算过了,今晚貌似必须要写题解了。
void init()//算出dis小于等于i的个数;
{
memset(ans,0,sizeof(ans));
memset(visit,false,sizeof(visit));
for(int i=0;i<n;i++)
{
if(visit[a[i]]==true)
dis[i]=i-num[a[i]],ans[dis[i]]++;
else
dis[i]=n,ans[n]++;
num[a[i]]=i;
visit[a[i]]=true;
}
cnt[n]=ans[n];
for(int i=n-1;i>=1;i--)
{
cnt[i]=cnt[i+1]+ans[i];
}
memset(visit,false,sizeof(visit));
num[n]=0;
//处理一下初始数组那里;
for(int i=n-1;i>=0;i--)///算出倒数几个不同的数的个数
{
if(!visit[a[i]])
num[i]=num[i+1]+1;
else
num[i]=num[i+1];
visit[a[i]]=true;
}
ans[0]=0;
for(int i=1;i<=n;i++)
if(dis[i-1]==n)
ans[i]=ans[i-1]+1;
else
ans[i]=ans[i-1];
}
ll dp[maxn];
void solve()///坐标还是从1开始把吧。
{
dp[1]=(ll)n;
for(int i=2;i<=n-1;i++)
{
dp[i]=dp[i-1]+(ll)(cnt[i]-ans[i-1])-(ll)num[n-i+1];
}
}
///还要处理好是前多少个
int q,temp;
int main()///i64
{
// freopen("1.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(ll i=0;i<n;i++)
scanf("%d",&a[i]);
init();
solve();
scanf("%d",&q);
for(ll i=0;i<q;i++)
{
scanf("%d",&temp),printf("%I64d\n",dp[temp]);
}
}
}
HDU 4455 线段树
最新推荐文章于 2019-12-18 20:07:00 发布