BZOJ 2120: 数颜色 && 2453: 维护队列 【带修莫队版题【也可以学黄学长分块
2017-01-18 15:33
603 查看
……学莫队QwQ 好神啊QwQ
复杂度什么的xjb讨论一下感觉好像挺对的23333
加个修改就相当于变成三维的查询……直接用三个指针,维护当前记录的左端点右端点和时间,
先把询问按照
第一关键字:左端点所在的块
第二关键字:右端点所在的块
第三关键字:前一个修改操作的时间
排序,然后xjb暴力做,yy一下可以证明……块大小是N^(2/3)的时候最优 于是就这么写咯……和普通莫队……没啥区别?
复杂度什么的xjb讨论一下感觉好像挺对的23333
加个修改就相当于变成三维的查询……直接用三个指针,维护当前记录的左端点右端点和时间,
先把询问按照
第一关键字:左端点所在的块
第二关键字:右端点所在的块
第三关键字:前一个修改操作的时间
排序,然后xjb暴力做,yy一下可以证明……块大小是N^(2/3)的时候最优 于是就这么写咯……和普通莫队……没啥区别?
#include<cmath> #include<cstdio> #include<cctype> #include<algorithm> #define MAXN 10005 using namespace std; int n,m; inline int read(){ register int ch = getchar(); while(!isdigit(ch)) ch = getchar(); register int rtn = 0 ; while(isdigit(ch)) rtn = rtn*10 + ch - '0' , ch = getchar() ; return rtn; } int a[MAXN] ; int col[MAXN] ; int yjq[MAXN] , laekov ; struct ASK{ int id,l,r,pre; ASK(){} ASK(int id,int l,int r,int pre): id(id),l(l),r(r),pre(pre){} bool operator < (const ASK ano) const { if(yjq[l]==yjq[ano.l]) return yjq[r]==yjq[ano.r] ? pre < ano.pre : yjq[r] < yjq[ano.r] ; else return yjq[l] < yjq[ano.l] ; } }ask[MAXN]; int cnt_ask; int ans[MAXN]; struct MODIFY{ int id,pos,v,pre; MODIFY(){} MODIFY(int id,int pos,int v,int pre): id(id),pos(pos),v(v),pre(pre){} }mdf[MAXN]; int cnt_mdf; int tot = 0 ; int cnt[1000006] ; inline void add(int x) {tot += (++cnt[x])==1 ;} inline void del(int x) {tot -= !(--cnt[x]) ;} inline void work(){ for(int i=1;i<=n;++i) col[i] = a[i] ; int L=1,R=1,TIME=0; add(col[L]); for(int i=1;i<=cnt_ask;++i){ int l = ask[i].l , r = ask[i].r , tim = ask[i].pre ; while(TIME<tim){ ++TIME; int pos = mdf[TIME].pos; col[pos] = mdf[TIME].v; if(pos>=L&&pos<=R) del(mdf[TIME].pre) , add(mdf[TIME].v); } while(TIME>tim){ col[mdf[TIME].pos] = mdf[TIME].pre; int pos = mdf[TIME].pos; if(pos>=L&&pos<=R) del(mdf[TIME].v) , add(mdf[TIME].pre); --TIME; } while(L<l) del(col[L++]); while(L>l) add(col[--L]); while(R<r) add(col[++R]); while(R>r) del(col[R--]); ans[ask[i].id] = tot ; } } char opt[5]; int now_pre = 0 ; int read_x,read_y; int main(){ freopen("1.in","r",stdin); n = read() , m = read() ; laekov = pow(n,2.0/3.0); for(int i=1;i<=n;++i) a[i] = col[i] = read() ; for(int i=1;i<=m;++i){ scanf("%s",opt) , read_x = read() , read_y = read(); if(opt[0]=='Q') ask[++cnt_ask] = ASK(cnt_ask,read_x,read_y,now_pre); else{ mdf[++cnt_mdf] = MODIFY(cnt_mdf,read_x,read_y,col[read_x]); col[read_x] = read_y ; now_pre = cnt_mdf ; } } sort(ask+1,ask+cnt_ask+1); work(); for(int i=1;i<=cnt_ask;++i) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- Linux ALSA声卡驱动之八:ASoC架构中的Platform
- bootsect.S 中文注释 ( linux-0.12 )
- shell 数组、字典、source、split简单实例
- opencv+人脸识别(识别出来是某个人)
- hadoop 序列化和排序,自定义分区
- 使用 sshpass 用于非交互的 ssh 密码验证登录
- linux cp/scp命令+scp命令详解
- 提高Tomcat性能的参数设置
- ECSHOP网站--ecshop全部表的含义
- shell脚本加密
- 使用libvirt技术监控虚拟机资源利用情况
- 理解RESTFul架构
- ECSHOP网站--商品页显示累计销售量
- ECSHOP网站--去掉Powered by ECShop版权
- 欢迎使用CSDN-markdown编辑器
- 常用adb shell命令
- Opencv鼠标响应
- crontab 不运行原因排查
- 2016 年度码云热门项目排行榜 TOP 50
- Bash脚本中进制转换