2120: 数颜色/2453: 维护队列
2017-05-31 20:16
295 查看
题目链接
题目大意:给一个数列,资磁单点修改和求[l,r]中不同数字个数
题解:正解:分块或带修莫队或者主席树。离散化暴力跑的飞快……
暴力:……
分块:pre[i]表示前一个和i相同颜色的球的所在位置
询问[l,r]中有多少个不同的数等价于[l,r]中有多少个pre[i]<l
块内按pre[i]排序,类似教主的魔法那题
留坑待填……
我的收获:劲劲劲
分块
题目大意:给一个数列,资磁单点修改和求[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; }
相关文章推荐
- 【BZOJ2453】维护队列/【BZOJ2120】数颜色 分块
- BZOJ2453: 维护队列&2120: 数颜色
- 【BZOJ】2453: 维护队列【BZOJ】2120: 数颜色 二分+分块(暴力能A)
- 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
- Bzoj 2453: 维护队列 && Bzoj 2120: 数颜色 分块,bitset
- 【BZOJ】【2120】数颜色 & 【2453】维护队列
- BZOJ 2120: 数颜色 && 2453: 维护队列 【带修莫队版题【也可以学黄学长分块
- BZOJ 2120 数颜色&2453 维护队列 [带修改的莫队算法]【学习笔记】
- BZOJ 2453: 维护队列&&BZOJ 2120 数颜色 分块
- bzoj2453 维护队列 & bzoj2120 数颜色 (带修改莫队)
- BZOJ 2120: 数颜色/BZOJ 2453: 维护队列 带修改莫队
- 【bzoj 2120】维护队列【bzoj 2453】数颜色 双倍经验!!!
- BZOJ[2120]数颜色/BZOJ[2453]维护队列 分块
- BZOJ 2120: 数颜色&&2453: 维护队列【双倍经验】
- [树状数组套权值线段树 || 分块] BZOJ 2120 数颜色 & BZOJ 2453 维护队列
- Bzoj 2120: 数颜色 && 2453: 维护队列 莫队,分块,bitset
- [BZOJ2120] 数颜色 && [bzoj2453] 维护队列(莫队 || 分块)
- 【bzoj 2120】维护队列【bzoj 2453】数颜色 双倍经验!!!
- BZOJ2453维护队列&&BZOJ2120数颜色
- 【BZOJ-2453&2120】维护队列&数颜色 分块 + 带修莫队算法