【2011集训队出题】数颜色

13 篇文章 0 订阅
10 篇文章 0 订阅

###Description

###Solution
这题和Dynamic len神似(这题代码也差不多),只是数据更小, n 2 n^2 n2暴力可以A。

###Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 50001
#define M 1000001
#define _N 250
using namespace std;
int a[N];
int map[M];
int tot=0;
struct node{
	int l,r;
	int z[_N],px[_N];
}b[_N];
bool bz[N*2];
int zz[N*2];
int next[N],last[N];
int s[_N][N*2];
int pos[N];
bool cmp(int x,int y)
{
	return next[x]<next[y];
}
int main()
{
	int n,m;
	cin>>n>>m;
	fo(i,0,n-1)
	{
		scanf("%d",&a[i]);
		if(!map[a[i]]) map[a[i]]=++tot;
		a[i]=map[a[i]];
	}
	memset(zz,-1,sizeof(zz));
	fo(i,0,n-1)
	{
		next[i]=n;
		last[i]=i;
		if(zz[a[i]]<0) zz[a[i]]=i;
		else
		{
			last[i]=zz[a[i]];
			next[last[i]]=i;
			zz[a[i]]=i;
		}
	}
	int t=int(sqrt(n));
	int l=0,r=t-1;
	int mxn=n/t+1;
	fo(i,1,n/t+1)
	{
		b[i].l=l,b[i].r=r;
		int cnt=0;
		fo(j,l,r)
		{
			pos[j]=i;
			s[i][a[j]]++;
			b[i].z[++cnt]=b[i].px[cnt]=j;
		}
		sort(b[i].px+1,b[i].px+r-l+2,cmp);
		l=r+1;
		r=min(l+t-1,n-1);
	}
	while(m--)
	{
		char ch[5];
		int x,y;
		scanf("%s %d %d",ch,&x,&y);
		if(ch[0]=='Q')
		{
			x--;y--;
			int ans=0;
			int l=pos[x],r=pos[y];
			if(l==r)
			{
				fo(i,x,y)
				if(next[i]>y) ans++;
				printf("%d\n",ans);
				continue;
			}
			if(x>b[l].l)
			{
				fo(i,x,b[l].r)
				if(next[i]>y) ans++;
				l++;
			}
			if(y<b[r].r)
			{
				fo(i,b[r].l,y)
				if(next[i]>y) ans++;
				r--;
			}
			fo(i,l,r)
			{
				int ll=0,rr=b[i].r-b[i].l+1;
				while(ll<rr-1)
				{
					int mid=(ll+rr)/2;
					if(next[b[i].px[mid]]<=y) ll=mid;
					else rr=mid; 
				}
				int q;
				if(next[b[i].px[rr]]<=y) q=rr;
				else q=ll;
				ans+=b[i].r-b[i].l-q+1;
			}
			printf("%d\n",ans);
		}
		else
		{
			x--;
			if(!map[y]) map[y]=++tot;
			y=map[y];
			next[last[x]]=next[x];
			int tt=pos[last[x]];
			sort(b[tt].px+1,b[tt].px+b[tt].r-b[tt].l+2,cmp);
			if(last[x]==x) last[next[x]]=next[x];
			else last[next[x]]=last[x];
			int l=pos[x],r=pos[x];
			s[l][a[x]]--;
			next[x]=n;
			last[x]=x;
			bool tf=false;
			fd(i,x-1,b[l].l)
			if(a[b[l].z[i-b[l].l+1]]==y)
			{
				last[x]=i;
				next[i]=x;
				tf=true;
				break;
			}
			if(!tf)
			{
				fd(i,l-1,1)
				if(s[i][y])
				{
					fd(j,b[i].r,b[i].l)
					if(a[b[i].z[j-b[i].l+1]]==y)
					{
						last[x]=j;
						next[j]=x;
						sort(b[i].px+1,b[i].px+b[i].r-b[i].l+2,cmp);
						tf=true;
						break;
					}
					if(tf) break;
				}
			}
			tf=false;
			fo(i,x+1,b[l].r)
			if(a[b[l].z[i-b[l].l+1]]==y)
			{
				next[x]=i;
				last[i]=x;
				tf=true;
				break;
			}
			if(!tf)
			{
				fo(i,r+1,mxn)
				if(s[i][y])
				{
					fo(j,b[i].l,b[i].r)
					if(a[b[i].z[j-b[i].l+1]]==y)
					{
						next[x]=j;
						last[j]=x;
						tf=true;
						break;
					}
					if(tf) break;
				}
			}
			a[x]=y;
			s[l][y]++;
			sort(b[l].px+1,b[l].px+b[l].r-b[l].l+2,cmp);
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值