1. 程式人生 > >Codeforces Round #406 (Div. 2) E. Till I Collapse(主席樹)

Codeforces Round #406 (Div. 2) E. Till I Collapse(主席樹)

esp type 個數 gif lan upd roo node .com

題目鏈接: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; }
View Code

Codeforces Round #406 (Div. 2) E. Till I Collapse(主席樹)