【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
题目描述
输入
输出
样例输入
2 3
1 2
Q 1 2
R 1 2
Q 1 2
样例输出
2
1
题解
分块+二分
两道一样的题。。。
对于每个i记录一个p[i],代表i前一个颜色与i相同的位置,没有则为-1。
那么对于区间[l,r]中的i,如果p[i]<l,那么i就是[l,r]中第一个出现c[i]颜色的,可以记录到答案中。
然后分成√n 个块,建立新数组对块中p[i]排序。
查询时,整块使用排序后的数组二分查找小于l的个数,多余部分暴力查询。
修改时,需要考虑3部分:i后面第一个c[j]==c[x],i后面第一个c[j]==y,i前面第一个c[j]==y。
于是我们还需要建立新数组对块中c[i]排序,并使用二分查找来完成这三个操作。
具体方法:x块内暴力查找,x块外二分查找。
这里压了大量的行,并使用flag减小花括号,不然太多行实在要看吐了QAQ。
还是别忘特判,另外注意i的含义,位置号或块号。
看到网上还有暴力修改的方法,不过亲测很慢,不推荐。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n , si , c[10010] , vc[10010] , p[10010] , vp[10010] , last[1000010];
char str[5];
void reset(int b)
{
int l = b * si , r = min((b + 1) * si - 1 , n - 1) , i;
for(i = l ; i <= r ; i ++ ) vc[i] = c[i] , vp[i] = p[i];
sort(vc + l , vc + r + 1) , sort(vp + l , vp + r + 1);
}
int query(int b , int lim)
{
int l = b * si , r = min((b + 1) * si - 1 , n - 1) , mid , ans = l - 1 , tl = l;
while(l <= r)
{
mid = (l + r) >> 1;
if(vp[mid] < lim) ans = mid , l = mid + 1;
else r = mid - 1;
}
return ans - tl + 1;
}
bool findc(int l , int r , int x)
{
int mid;
while(l <= r)
{
mid = (l + r) >> 1;
if(vc[mid] == x) return 1;
else if(vc[mid] < x) l = mid + 1;
else r = mid - 1;
}
return 0;
}
int main()
{
int m , i , j , x , y , ans , flag , l , r;
scanf("%d%d" , &n , &m);
si = (int)sqrt(n);
memset(last , -1 , sizeof(last));
for(i = 0 ; i < n ; i ++ ) scanf("%d" , &c[i]) , p[i] = last[c[i]] , last[c[i]] = i;
for(i = 0 ; i * si < n ; i ++ ) reset(i);
while(m -- )
{
scanf("%s%d%d" , str , &x , &y);
x -- ;
if(str[0] == 'Q')
{
y -- ;
ans = 0;
if(x / si == y / si) for(i = x ; i <= y ; i ++ ) ans += (p[i] < x);
else
{
for(i = x / si + 1 ; i < y / si ; i ++ ) ans += query(i , x);
for(i = x ; i < (x / si + 1) * si ; i ++ ) ans += (p[i] < x);
for(i = y / si * si ; i <= y ; i ++ ) ans += (p[i] < x);
}
printf("%d\n" , ans);
}
else
{
if(c[x] == y) continue;
flag = 0;
for(i = x + 1 ; !flag && i < (x / si + 1) * si && i < n ; i ++ ) if(p[i] == x) p[i] = p[x] , reset(i / si) , flag = 1;
for(i = x / si + 1 ; !flag && i * si < n ; i ++ )
{
l = i * si , r = min((i + 1) * si - 1 , n - 1);
if(findc(l , r , c[x])) for(j = l ; !flag && j <= r ; j ++ ) if(c[j] == c[x]) p[j] = p[x] , reset(i) , flag = 1;
}
c[x] = y;
flag = 0;
for(i = x + 1 ; !flag && i < (x / si + 1) * si && i < n ; i ++ ) if(c[i] == c[x]) p[i] = x , reset(i / si) , flag = 1;
for(i = x / si + 1 ; !flag && i * si < n ; i ++ )
{
l = i * si , r = min((i + 1) * si - 1 , n - 1);
if(findc(l , r , c[x])) for(j = l ; !flag && j <= r ; j ++ ) if(c[j] == c[x]) p[j] = x , reset(i) , flag = 1;
}
flag = 0;
for(i = x - 1 ; !flag && i >= x / si * si ; i -- ) if(c[i] == c[x]) p[x] = i , flag = 1;
for(i = x / si - 1 ; !flag && ~i ; i -- )
{
l = i * si , r = min((i + 1) * si - 1 , n - 1);
if(findc(l , r , c[x])) for(j = r ; !flag && j >= l ; j -- ) if(c[j] == c[x]) p[x] = j , flag = 1;
}
if(!flag) p[x] = -1;
reset(x / si);
}
}
}
【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分的更多相关文章
- BZOJ2453维护队列&&BZOJ2120数颜色
2016-05-28 11:20:22 共同的思路: 维护某种颜色上一次在哪里出现pre,可以知道当pre<询问的l时更新答案 块内按照pre排序 修改的时候重新O(n)扫一遍,如果和之前的不一 ...
- [BZOJ2120] 数颜色 && [bzoj2453] 维护队列(莫队 || 分块)
传送门 只有第一个,第二个权限题. 分块,然而wa,没看出来错在哪里,有时间再看. #include <cmath> #include <cstdio> #include &l ...
- bzoj2120 数颜色 分块
分块大法好 orz 处理出每个点的前驱和后继位置. 暴力修改,查询就在每个整块里查询pre<l的,暴力跑两边就好了 #include<cstdio> #include<cstr ...
- Luogu 1903 数颜色 | 分块
Luogu 1903 数颜色 | 分块 莫队不会啊-- 这道题直接分块也能卡过! 这道题的做法很有趣:对于每个位置i,记录它的颜色a[i]上一次出现的位置,记为pre[i]. 这样在查询一个区间[l, ...
- BZOJ2120 数颜色 【带修莫队】
BZOJ2120 数颜色 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到 ...
- 【BZOJ2453】维护队列/【BZOJ2120】数颜色 分块
[BZOJ2453]维护队列 Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色 ...
- 【BZOJ-2453&2120】维护队列&数颜色 分块 + 带修莫队算法
2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 653 Solved: 283[Submit][Status][Discuss] ...
- Bzoj 2453: 维护队列 && Bzoj 2120: 数颜色 分块,bitset
2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 578 Solved: 247[Submit][Status][Discuss] ...
- BZOJ2453: 维护队列
2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 183 Solved: 89[Submit][Status] Descripti ...
随机推荐
- 【nat---basic,napt,easy ip】
display nat :显示nat 信息 debugging nat :对nat进行调试 reset nat session:擦除nat连接配置 basic-nat:公网->私网(一对一) n ...
- 响应式布局--设置rem自适应
//designWidth:设计稿的实际宽度值,需要根据实际设置 //maxWidth:制作稿的最大宽度值,需要根据实际设置 //这段js的最后面有两个参数记得要设置,一个为设计稿实际宽度,一个为制作 ...
- Scala语法(三)
模式匹配 1)match val a = 1 val b=a match { *// a match { }返回值赋予变量 b case 1 => "red" case 2 ...
- centos安装zabbix(server+agent)
本文包含zabbix_server编译安装,zabbix_agent编译安装,中文字体修正 Mysql模板监控,Nginx模板监控,以及简单的web页面的使用 中文乱码的解决方案 zabbix乱码是字 ...
- c#vs连接SQL sever数据库入门操作
对于需要连接数据库的项目,可以参考的简单初级代码.实现打开数据库,读入数据功能 using System; using System.Collections.Generic; using System ...
- Vue-router使用
Vue路由:--------------------------------------------------------1 .Vue-rouer入门2 .子路由3 .路由传参4 .多路由区域操作5 ...
- CCS实例,网页栏目
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- VS2010安装MVC3出错
开始已经在电脑上安装了VS2010以及SP1,还装了MVC4的相关升级包.最后项目中又要用MVC3,然后又去安装MVC3的安装包,但是在安装的过程就出现了问题.一直安装不成功,最后在 ...
- 【数据结构】 Queue 的简单实现
[数据结构] Queue 的简单实现 public class XQueue<T> { /// <summary> /// 第一个元素 /// </summary> ...
- .netcore centos环境搭建实战
步骤 1. 安装VMware Workstation 下载地址:https://my.vmware.com/cn/web/vmware/info/slug/desktop_end_user_compu ...