HDU 4455 线段树

来源:互联网 发布:js中怎么删除数组元素 编辑:程序博客网 时间:2024/05/22 12:41
//hdu 4455 貌似是dp吧,写完还要改名字;//////10^6 数,10^4查询//防止tle////维护一个最后位置,维护一个距离,扫一遍,来处理;//防止mle#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cstdlib>#define maxn 1001010#define ll __int64using 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]);        }    }}

0 0