题目大意:给一个数列,资磁单点修改和求[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;
}
本文介绍了一种使用分块算法解决特定问题的方法。该算法适用于数列的单点修改及区间不同元素计数的问题,通过预处理和块内排序提高查询效率。
358

被折叠的 条评论
为什么被折叠?



