【莫队算法】URAL - 2080 - Wallet

http://www.cnblogs.com/icode-girl/p/5783983.html

要注意卡片没有都被使用的情况。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 100010
int K,n,a[N],nex[N],now[N],m,anss[N];
bool vis[N];
struct ASK{int l,r,p;}Q[N];
int num[N];
bool operator < (const ASK &a,const ASK &b)
{return num[a.l]!=num[b.l] ? num[a.l]<num[b.l] : a.r<b.r;}
void makeblock()
{
    int sz=sqrt(n),sum=1; if(!sz) sz=1;
    for(;sum*sz<n;++sum)
      {
        int r=sum*sz;
        for(int i=sz*(sum-1)+1;i<=r;++i)
		  num[i]=sum;
      }
    for(int i=sz*(sum-1)+1;i<=n;++i)
	  num[i]=sum;
}
int T[N],ans;
void Insert(int x)
{
	if(!T[x]) ++ans;
	++T[x];
}
void Delete(int x)
{
	--T[x];
	if(!T[x]) --ans;
}
int main()
{
	//freopen("c.in","r",stdin);
	scanf("%d%d",&K,&n);
	for(int i=1;i<=n;++i)
	  scanf("%d",&a[i]);
	int k=0;
	for(int i=1;i<=n;++i)
	  if(!vis[a[i]])
	    {
	      ++k;
	      vis[a[i]]=1;
	      printf("%d%c",a[i],k==K ? '\n' : ' ');
	    }
	for(int i=1;i<=K;++i)
	  if(!vis[i])
	    {
	      ++k;
	      printf("%d%c",i,k==K ? '\n' : ' ');
	    }
	for(int i=n;i>=1;--i)
	  {
	  	nex[i]=now[a[i]];
	  	now[a[i]]=i;
	  }
	for(int i=1;i<=n;++i)
	  if(nex[i]>i+1)
	    {
	      Q[++m].l=i+1;
	      Q[m].r=nex[i]-1;
	      Q[m].p=i;
	    }
	  else if(nex[i]==i+1)
	    anss[i]=0;
	  else
	    anss[i]=K-1;
	makeblock();
	sort(Q+1,Q+m+1);
	for(int i=Q[1].l;i<=Q[1].r;++i) Insert(a[i]);
    anss[Q[1].p]=ans;
    for(int i=2;i<=m;++i)
      {
        if(Q[i].l<Q[i-1].l){for(int j=Q[i-1].l-1;j>=Q[i].l;--j)Insert(a[j]);}
        else{for(int j=Q[i-1].l;j<Q[i].l;++j)Delete(a[j]);}
        if(Q[i].r<Q[i-1].r){for(int j=Q[i-1].r;j>Q[i].r;--j)Delete(a[j]);}
        else{for(int j=Q[i-1].r+1;j<=Q[i].r;++j)Insert(a[j]);}
        anss[Q[i].p]=ans;
      }
	for(int i=1;i<=n;++i)
	  printf("%d\n",anss[i]);
	return 0;
}
posted @ 2017-02-07 17:37  AutSky_JadeK  阅读(138)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト