嗯…直接贴板子了,(注释写了点)..
模板
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],belong[maxn],L[1010],R[1010],block,num;//a数组存取原始数据,belong数组表示每个数属于哪一块方便调用,L和R表示各块左右端点,block各块大小,num块数量
void change(int l,int r,int add)//修改,视情况而定
{
//略..(可见下面模板题)
}
int query(int l,int r)//查询,同上
{
//略..
}
void build(int n)//建立各块(各个分块这个操作大致一样)
{
block=sqrt(n);//大小
num=n/block;if(n%block)num++;//如果不整除显然数量加个1
for(int i=1;i<=num;i++)
L[i]=(i-1)*block+1,R[i]=i*block;//左右端点
R[num]=n; //最后一个右端点一定是结尾
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1; //belong数组
//初始状态维护......(省略)
}
int main()//读入
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(n);
//询问......(省略)
}
模板题–洛谷P1903 数颜色
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
为了满足墨墨的要求,你知道你需要干什么了吗?
输入输出格式
输入格式:
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。
第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。
第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
输出格式:
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
基本是裸的,不过数据要稍微离散下,再加个bitset加速(离散还不怎么会…)
代码(最慢点196ms)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int a[maxn],t[maxn],belong[maxn],num,L[1010],R[1010],mp[1000010],cnt=0,block;
bitset<11010>bst[4010],ans;bool vis[11010];
void lisan(int n)//离散
{
int m;
for(int i=1;i<=n;i++)
t[i]=a[i];
sort(t+1,t+n+1);
m=unique(t+1,t+n+1)-t-1;
for(int i=1;i<=n;i++)
mp[a[i]]=a[i]=lower_bound(t+1,t+1+m,a[i])-t;
}
void build(int n)
{
block=sqrt(n);num=n/block;
if(n%block)num++;
for(int i=1;i<=num;i++)
L[i]=(i-1)*block+1,R[i]=i*block;
R[num]=n;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for(int i=1;i<=num;i++)//初始化
{
bst[i].reset();
for(int j=L[i];j<=R[i];j++)
bst[i].set(a[j]);
}
}
int query(int l,int r)
{
if(belong[l]==belong[r])//注意!!这个情况要特判!基本所有分块的查询都是
{
int res=0;
memset(vis,0,sizeof vis);
for(int i=l;i<=r;i++)
{if(!vis[a[i]])vis[a[i]]=1,res++;}
return res;
}
ans.reset();
for(int i=l;i<=R[belong[l]];i++)
ans.set(a[i]);
for(int i=belong[l]+1;i<belong[r];i++)//暴力搞
ans|=bst[i];
for(int i=L[belong[r]];i<=r;i++)
ans.set(a[i]);
return ans.count();
}
void change(int pos,int to)//同上暴力
{
if(mp[to]==-1)++cnt,mp[to]=cnt+10000;
a[pos]=mp[to];
bst[belong[pos]].reset();
for(int i=L[belong[pos]];i<=R[belong[pos]];i++)
bst[belong[pos]].set(a[i]);
return;
}
int main()
{
int n,m,l,r;char op;
memset(mp,-1,sizeof mp);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
lisan(n);
build(n);
while(m--)
{
scanf(" %c",&op);
scanf("%d%d",&l,&r);
if(op=='Q')printf("%d\n",query(l,r));
else change(l,r);
}
return 0;
}