您的位置:首页 > 运维架构

2120: 数颜色/2453: 维护队列

2017-05-31 20:16 295 查看
题目链接

题目大意:给一个数列,资磁单点修改和求[l,r]中不同数字个数

题解:正解:分块或带修莫队或者主席树。离散化暴力跑的飞快……

暴力:……

分块:pre[i]表示前一个和i相同颜色的球的所在位置

询问[l,r]中有多少个不同的数等价于[l,r]中有多少个pre[i]<l

块内按pre[i]排序,类似教主的魔法那题

留坑待填……

我的收获:劲劲劲

#include <iostream>
#include <cstdio>
using namespace std;

int n,m,tot,T;
int mp[1001005],f[11005],a[11005];

int ID(int x){return mp[x]?mp[x]:mp[x]=++tot;}

int query(int l,int r)
{
int ans=0;++T;
for(int i=l;i<=r;i++)
if(f[a[i]]!=T)
++ans,f[a[i]]=T;
return ans;
}

void work()
{
int x,y;
char opt[5];
while(m--)
{
scanf("%s%d%d",opt,&x,&y);
if(opt[0]=='Q') printf("%d\n",query(x,y));
else a[x]=ID(y);
}
}

void init()
{
cin>>n>>m;
for(int i=1,x;i<=n;i++)
scanf("%d",&x),a[i]=ID(x);
}

int main()
{
init();
work();
return 0;
}


分块

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;

#define M 10005

#define opes for(int i=l;i<=r;i++)
#define opel for(int i=l;i<=min(pos[l]*blo,r);i++)
#define oper for(int i=(pos[r]-1)*blo+1;i<=r;i++)
#define opea for(int i=pos[l]+1;i<=pos[r]-1;i++)

int n,q,num,blo;
int a[M],pos[M],pre[M],b[M],last[1000005];//pre[i]为原数组,b[i]为排序后数组

int find(int x,int v)
{
int l=(x-1)*blo+1,r=min(x*blo,n);
int ans=lower_bound(b+l,b+r+1,v)-b;
return ans-l;
}

void reset(int x)
{
int l=(x-1)*blo+1,r=min(x*blo,n);
opes b[i]=pre[i];
sort(b+l,b+r+1);
}

int query(int l,int r)
{
int ret=0;
if(pos[l]==pos[r]) opes ret+=pre[i]<l;
else
{
opel ret+=pre[i]<l;
oper ret+=pre[i]<l;
opea ret+=find(i,l);
}
return ret;
}

void updata(int x,int v)//暴力修改
{
for(int i=1;i<=n;i++) last[a[i]]=0;
a[x]=v;
for(int i=1;i<=n;i++)
{
int t=pre[i];
pre[i]=last[a[i]];
if(t!=pre[i]) reset(pos[i]);
last[a[i]]=i;
}
}

void work()
{
char ch[5];
int x,y;
for(int i=1;i<=q;i++)
{
scanf("%s%d%d",ch,&x,&y);
if(ch[0]=='Q') printf("%d\n",query(x,y));
else updata(x,y);
}
}

void init()
{
cin>>n>>q;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
blo=sqrt(n);num=(n-1)/blo+1;
for(int i=1;i<=n;i++){
pre[i]=last[a[i]];
last[a[i]]=i;
pos[i]=(i-1)/blo+1;
}
for(int i=1;i<=num;i++) reset(i);
}

int main()
{
init();
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: