HDU 4455 线段树

//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]);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值