题目链接:Codeforces Round #406 (Div. 2) E. Till I Collapse
题意:
给你n个数,对于每一个k(1<=k<=n),划分区间,每个区间只能有k个不同的数字,
问最小的划分区间的个数。
题解:
用主席树倒着将数插入,对于每个区间询问第k个不同数的位置就行了。
#include<bits/stdc++.h> #define F(i,a,b) for(int i=a;i<=b;i++) #define ___ freopen("in.txt","r",stdin); using namespace std; typedef long long ll; const int N=1e5+7; int root[N],a[N],cnt,pre[N],n; struct node{int l,r,sum;}T[N*40]; void update(int l,int r,int &x,int y,int pos,int val) { T[++cnt]=T[y],T[x=cnt].sum+=val; if(l==r)return; int mid=l+r>>1; if(mid>=pos)update(l,mid,T[x].l,T[y].l,pos,val); else update(mid+1,r,T[x].r,T[y].r,pos,val); } int query(int l,int r,int x,int k) { if(l==r)return l; int mid=l+r>>1; if(k<=T[T[x].l].sum)return query(l,mid,T[x].l,k); else return query(mid+1,r,T[x].r,k-T[T[x].l].sum); } int main() { scanf("%d",&n); F(i,1,n)scanf("%d",a+i); for(int i=n;i>0;i--) { update(1,n,root[i],root[i+1],i,1); if(pre[a[i]])update(1,n,root[i],root[i],pre[a[i]],-1); pre[a[i]]=i; } F(i,1,n) { int now=1,ans=0; while(now<=n) { if(T[root[now]].sum>i)now=query(1,n,root[now],i+1); else now=n+1; ans++; } printf("%d%c",ans," \n"[i==n]); } return 0; }
时间: 2024-11-07 19:01:26