bzoj 2120: 数颜色
2016-03-18 23:03
393 查看
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #define M 1000009 using namespace std; int block,n,m,a[M],b[M],pre[M],pos[M],last[M],l[M],r[M],m1; int ask(int a1,int a2) { int ans=0; if(pos[a1]==pos[a2]) { for(int i=a1;i<=a2;i++) if(b[i]<a1) ans++; } else { for(int i=a1;i<=r[pos[a1]];i++) if(b[i]<a1) ans++; for(int i=l[pos[a2]];i<=a2;i++) if(b[i]<a1) ans++; for(int i=pos[a1]+1;i<pos[a2];i++) ans+=lower_bound(pre+l[i],pre+r[i]+1,a1)-pre-l[i]; } return ans; } void jian(int i) { l[i]=(i-1)*block+1; r[i]=min(n,i*block); for(int j=l[i];j<=r[i];j++) pre[j]=b[j]; sort(pre+l[i],pre+r[i]+1); } void gai(int x,int y) { for(int i=1;i<=n;i++) last[a[i]]=0; a[x]=y; for(int i=1;i<=n;i++) { int t=b[i]; b[i]=last[a[i]]; if(t!=last[a[i]]) jian(pos[i]); last[a[i]]=i; } } int main() { scanf("%d%d",&n,&m1); for(int i=1;i<=n;i++) scanf("%d",&a[i]); block=(int)sqrt(n+log(2*n)/log(2)); m=n/block; if(n%block) m++; for(int i=1;i<=n;i++) { b[i]=last[a[i]]; last[a[i]]=i; pos[i]=(i-1)/block+1; } for(int i=1;i<=m;i++) jian(i); for(int i=1;i<=m1;i++) { char ch[5]; int a1,a2; scanf("%s%d%d",ch,&a1,&a2); if(ch[0]=='Q') printf("%d\n",ask(a1,a2)); else gai(a1,a2); } return 0; }
暴力分块,每个点存下一个与他相同颜色的在哪,每个块内排序,找的时候首尾暴力判断每个点下一个颜色在不在区间外,不在就答案加加,中间二分。修改时重建每个点存的下一个点,
如果改了,就重建这个块。
相关文章推荐
- AsyncTask之内存泄露
- Genymotion添加模拟器时报“Unable to create virtual device,Server returned HTTP status code 0”
- 【bzoj3524/2223】[Poi2014]Couriers/[Coci 2009]PATULJCI 主席树
- 1006-加法变乘法
- pip install mysql-connector-python安装时报错不满足requirement
- vim常用快捷键
- [leetcode 277]Find the Celebrity---------找名人
- PAT 乙级 1010.一元多项式求导
- LeetCode 之 Sort Colors
- 打印杨辉三角
- 欢迎使用CSDN-markdown编辑器
- 同步和异步的理解
- nyoj58最少步数
- Swift自定义转场动画
- 第五十六天
- dns泛解析漫谈
- [android] 字符乱码问题的处理
- 缓动动画 animate
- 删除桌面顽固文件的批处理文件法
- 使用openpyxl修改Excel文件,日期累加写入