BZOJ2453: 维护队列&2120: 数颜色
2016-10-25 20:38
357 查看
pre[i]表示与i颜色相同的上一个在pre[i]的位置,nex[i]表示下一个,那么询问可以转化成问[l,r]里pre<l的有多少个
分块,每个块内将pre排序。
询问时扫过去每个块内二分一下<l的位置,两端的块在块内扫一遍
将第x位置修改成y时要修改3个pre值,pre[x],pre[nex[x]],x后第一个y颜色的pre,用nex和set可以辅助查找,修改完在自己的块内重新排序
code:(写的很丑)
分块,每个块内将pre排序。
询问时扫过去每个块内二分一下<l的位置,两端的块在块内扫一遍
将第x位置修改成y时要修改3个pre值,pre[x],pre[nex[x]],x后第一个y颜色的pre,用nex和set可以辅助查找,修改完在自己的块内重新排序
code:(写的很丑)
#include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<cmath> #include<ctime> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<climits> #include<complex> #include<iostream> #include<algorithm> using namespace std; const int maxn = 21000; set<int>S[maxn]; set<int>::iterator it; struct node { int id,x1,x2; }a[maxn]; struct q { int x,i; }p[maxn]; int pre[maxn],nex[maxn]; int st[maxn],id[maxn],col[maxn]; int N,n,m,k; char str[maxn]; int dy[1100000]; bool cmp1(node x,node y){return x.x1<y.x1;} bool cmp2(node x,node y){return x.id<y.id;} bool cmp3(q x,q y){return x.x<y.x;} int find_f(int l,int r,int x) { while(l<=r) { int mid=(l+r)>>1; if(p[mid].x<x)l=mid+1; else r=mid-1; } return l-1; } void P() { for(int i=1;i<=n;i++) { pre[i]=col[a[i].x2]; col[a[i].x2]=i; p[i].i=i; p[i].x=pre[i]; } for(int i=1;i<=n;i++)col[i]=n+1; for(int i=n;i>=1;i--) { nex[i]=col[a[i].x2]; col[a[i].x2]=i; } for(int i=id[1];i<=id ;i++) sort(p+st[i],p+st[i+1],cmp3); } void update(int x,int c) { int t=id[x]; for(int i=st[t];i<st[t+1];i++) { if(p[i].i==x) { p[i].x=c; break; } } sort(p+st[t],p+st[t+1],cmp3); } void solve() { while(m--) { scanf("%s",str); int x,y;scanf("%d%d",&x,&y); if(str[0]=='Q') { int t1=id[x],t2=id[y]; int ret=0; if(t1+1>=t2) { for(int i=st[t1];i<st[t2+1];i++) if(p[i].i>=x&&p[i].i<=y&&p[i].x<x)ret++; } else { for(int i=st[t1];i<st[t1+1]&&p[i].x<x;i++) if(p[i].i>=x) ret++; for(int i=t1+1;i<t2;i++) ret+=find_f(st[i],st[i+1]-1,x)-st[i]+1; for(int i=st[t2];i<st[t2+1]&&p[i].x<x;i++) if(p[i].i<=y) ret++; } printf("%d\n",ret); } else { if(!dy[y]) { dy[y]=++k; S[k].insert(0); S[k].insert(n+1); } y=dy[y]; if(pre[x]) nex[pre[x]]=nex[x]; if(nex[x]!=n+1) { pre[nex[x]]=pre[x]; update(nex[x],pre[x]); } S[a[x].x2].erase(x); a[x].x2=y; it=S[y].lower_bound(x); int xx=(*it); it--;int xxx=(*it); if(xx!=n+1) { pre[xx]=x; update(xx,x); } if(xxx) nex[xxx]=x; nex[x]=xx; pre[x]=xxx; update(x,pre[x]); S[y].insert(x); } } } int main() { scanf("%d%d",&n,&m); N=sqrt(n); for(int i=1;i<=n;i++) { id[i]=(i-1)/N+1; scanf("%d",&a[i].x1); a[i].id=i; } for(int i=id[1];i<=id ;i++) st[i]=(i-1)*N+1; st[id +1]=n+1; sort(a+1,a+n+1,cmp1); a[0].x1=a[1].x1-1; for(int i=1;i<=n;i++) { if(a[i].x1!=a[i-1].x1) { k++; dy[a[i].x1]=k; S[k].insert(0); S[k].insert(n+1); } a[i].x2=k; S[k].insert(a[i].id); } sort(a+1,a+n+1,cmp2); P(); solve(); return 0; }
相关文章推荐
- BZOJ 2120 数颜色&2453 维护队列 [带修改的莫队算法]【学习笔记】
- Bzoj 2453: 维护队列 && Bzoj 2120: 数颜色 分块,bitset
- 【BZOJ】【2120】数颜色 & 【2453】维护队列
- [BZOJ2120] 数颜色 && [bzoj2453] 维护队列(莫队 || 分块)
- BZOJ 2453: 维护队列&&BZOJ 2120 数颜色 分块
- bzoj2453 维护队列 & bzoj2120 数颜色 (带修改莫队)
- [树状数组套权值线段树 || 分块] BZOJ 2120 数颜色 & BZOJ 2453 维护队列
- BZOJ 2120: 数颜色 && 2453: 维护队列 【带修莫队版题【也可以学黄学长分块
- Bzoj 2120: 数颜色 && 2453: 维护队列 莫队,分块,bitset
- BZOJ 2120: 数颜色&&2453: 维护队列【双倍经验】
- BZOJ2453维护队列&&BZOJ2120数颜色
- 【BZOJ2453】维护队列/【BZOJ2120】数颜色 分块
- 【bzoj 2120】维护队列【bzoj 2453】数颜色 双倍经验!!!
- 【BZOJ-2453&2120】维护队列&数颜色 分块 + 带修莫队算法
- BZOJ 2120: 数颜色/BZOJ 2453: 维护队列 带修改莫队
- BZOJ[2120]数颜色/BZOJ[2453]维护队列 分块
- 【BZOJ】2453: 维护队列【BZOJ】2120: 数颜色 二分+分块(暴力能A)
- 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
- 【bzoj 2120】维护队列【bzoj 2453】数颜色 双倍经验!!!
- 【BZOJ 2453|bzoj 2120】 2453: 维护队列 (分块+二分)