2019 ccpc 10th Shandong Province E - BaoBao Loves Reading

Main idea:

Give a sequence of reading. Miao needs to read these books from beginning to end, but the size of the table is limited. If the size of the table is i, when there are i books on the table, he needs to put the first books he has read back on the shelf, and then bring new books. If there are books he wants to read on the table, he doesn't need to take them. Ask how many times the table can be taken when its size is n.

Topic idea:

Think about the situation when you need to take books, that is, whether the number of different books between the book you took this time and the last time you took this book is larger than the size of the table. If the table can put different numbers in this range, does it mean that you don't need to take books? If the table is smaller than this different number, you need to take books.

Use the chairman tree template to find the number of different numbers in the range (RE or MLE in the range, WA in the small range)

#include<stdio.h>
#include<map>
#include<string.h>
#include<iostream>
#define ll long long
using namespace std;
const int MAXN=1e5+5;
struct Tree{
    int l ,r,sum;
}T[MAXN*40];
int root[MAXN],a[MAXN],b[MAXN],cnt,sz;
int Next[MAXN],Find[MAXN],ans[MAXN];
int mm[MAXN];
inline int read()
{
    int k=0;
    char f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar() )
        if(c=='-')
            f=-1;
    for(;isdigit(c);c=getchar() )
        k=k*10+c-'0';
    return k*f;
}
void add(int x,int val)
{
    ans[x]+=val;
}
int build(int l,int r)
{
    int rt=++cnt;
    T[rt].sum=0;
    if(l<r){
        int mid=(l+r)/2;
        T[rt].l=build(l,mid);
        T[rt].r=build(mid+1,r);
    }
    return rt;
}
void Updata(int l,int r,int &x,int y,int pos,int val)
{
    T[++cnt]=T[y];T[cnt].sum+=val,x=cnt;
    if(l==r)return ;
    int mid=(l+r)/2;
    if(mid>=pos)
        Updata(l,mid,T[x].l,T[y].l,pos,val);
    else
        Updata(mid+1,r,T[x].r,T[y].r,pos,val);
}
int Query(int L,int R,int l,int r,int rt)
{
    int ret=0;
    if(l<=L&&R<=r){
        return T[rt].sum;
    }
    int mid=(L+R)/2;
    if(l<=mid)ret+=Query(L,mid,l,r,T[rt].l);
    if(r>mid)ret+=Query(mid+1,R,l,r,T[rt].r);
    return ret;
}
int main()
{
    int t;
    t=read();
    while(t--){
        int n;
        n=read();
        cnt=0;
        memset(ans,0,sizeof(int)*(n+2));
        memset(Next,0,sizeof(int)*(n+2));
        memset(mm,0,sizeof(int)*(n+2));
        root[0]=build(1,n);
        for(int i=1;i<=n;i++){
            a[i]=read();
            Find[i]=Next[a[i]];
            Next[a[i]]=i;
        }
        for(int i=1;i<=n;i++){
            if(!mm[a[i]]){
                Updata(1,n,root[i],root[i-1],i,1);
            }
            else{
                int tmp=0;
                Updata(1,n,tmp,root[i-1],mm[a[i]],-1);
                Updata(1,n,root[i],tmp,i,1);

           }
            mm[a[i]]=i;
        }
        for(int i=1;i<=n;i++){
            if(Find[i]==0)add(1,1);
            else{
                int now=Query(1,n,Find[i],i,root[i]);
                add(1,1);add(now,-1);
            }
        }
        for(int i=1;i<=n;i++){
            ans[i]+=ans[i-1];
            printf("%d",ans[i]);
            if(i==n)printf("\n");
            else printf(" ");
        }
    }
}

Posted on Fri, 08 Nov 2019 14:20:06 -0500 by Yari