Description

"Hey! I have an awesome task with chameleons, 5 th task for Saturday’s competition."

"Go ahead. . . "

(...)

“That’s too difficult, I have an easier one, they won’t even solve that one.”

“You are given an array of N integers from the interval [1, K]. You need to process M queries. The first type of query requires you to change a number in the array to a different value, and the second type of query requires you to determine the length of the
shortest contiguous subarray of the current array that contains all numbers from 1 to K.”

“Hm, I can do it in O(N^6 ). What’s the limit for N?”

Input

The first line of input contains the integers N, K and M (1 <= N, M <= 100 000, 1 <= K <= 50). The second line of input contains N integers separated by space, the integers from the array. After that, M queries follow, each in one of the following two forms:

• “1 p v” - change the value of the p th number into v (1 <= p <= N, 1 <= v <= K)

• “2” - what is the length of the shortest contiguous subarray of the array containing all the integers from 1 to K

Output

The output must consist of the answers to the queries of the second type, each in its own line. If the required subarray doesn’t exist, output −1.

Sample Input

4 3 5

2 3 1 2

2

1 3 3

2

1 1 1

2

6 3 6

1 2 3 2 1 1

2

1 2 1

2

1 4 1

1 6 2

2

Sample Output

3

-1

4

3

3

4

题意:给你一段长为n的区间,区间内有k(k<=50)种颜色,让你每次更新后找到最短的连续区间,使得这个区间包含全部k种颜色,颜色可以有重复。

思路:一开始的思路是每次更新都用set维护,维护每一种颜色到区间两端点的最近距离,但是这样已更新所有数据都乱了= =,而且时间复杂度也爆了,所以要用别的方法。我们可以在线段树中开两个vector<pair<ll,int> >lo,re,分别表示左端点往右走的最多50种状态,以及右端点往左走的最多50种状态,那么b[i].mindis=min(b[i*2].mindis,b[i*2+1].mindis),然后就是要中间区间的合并了,我们用两个指针,一个p1指向左子树离b[i*2].r的最远的那种状态,然后另一个p2指向右子树离b[i*2+1].l最近的那种状态,每一次判断它们或起来是不是包含全部k种颜色,如果没有的话,p2往右移,如果恰好包含,那么再使得p1向右移。

ps:用pair写代码减少了很多,看着也舒服..

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 600000
#define maxn 100050
int a[maxn],k; struct node{
int l,r;
vector< pair<ll,int> >lo,re;
ll state;
int mindis;
}b[4*maxn]; void pushup(int th)
{
int i,j,siz;
b[th].lo=b[th*2].lo;
b[th].re=b[th*2+1].re; siz=b[th*2].lo.size();
ll now=b[th*2].lo[siz-1].first;
for(i=0;i<b[th*2+1].lo.size();i++ ){
if((now|b[th*2+1].lo[i].first )==now )continue;
now=(now|b[th*2+1].lo[i].first);
b[th].lo.push_back(make_pair(now,b[th*2+1].lo[i].second) );
} siz=b[th*2+1].re.size();
now=b[th*2+1].re[siz-1].first;
for(i=0;i<b[th*2].re.size();i++ ){
if((now|b[th*2].re[i].first )==now )continue;
now=(now|b[th*2].re[i].first );
b[th].re.push_back(make_pair(now,b[th*2].re[i].second) );
} b[th].state=(b[th*2].state|b[th*2+1].state);
b[th].mindis=min(b[th*2].mindis,b[th*2+1].mindis); ll state=(1LL<<k)-1;
int weizhi; j=0;
for(i=b[th*2].re.size()-1;i>=0;i--){
now=b[th*2].re[i].first;
weizhi=b[th*2].re[i].second;
while(j<b[th*2+1].lo.size()){
if((b[th*2+1].lo[j].first|now)==state ){
b[th].mindis=min(b[th].mindis,b[th*2+1].lo[j].second-weizhi+1 );break;
}
j++;
}
}
} void build(int l,int r,int th)
{
int mid;
b[th].l=l;b[th].r=r;
if(l==r){
b[th].lo.clear();
b[th].lo.push_back(make_pair(1LL<<a[l],l) ); b[th].re.clear();
b[th].re.push_back(make_pair(1LL<<a[l],r)); b[th].state=(1LL<<a[l]);
b[th].mindis=inf;return;
}
mid=(l+r)/2;
build(l,mid,th*2);
build(mid+1,r,th*2+1);
pushup(th);
} void update(int idx,int num,int th)
{
int mid;
if(b[th].l==idx && b[th].r==idx){
b[th].lo.clear();
b[th].lo.push_back(make_pair(1LL<<num,b[th].l) ); b[th].re.clear();
b[th].re.push_back(make_pair(1LL<<num,b[th].r)); b[th].state=(1LL<<num);
b[th].mindis=inf;return; }
mid=(b[th].l+b[th].r)/2;
if(idx<=mid)update(idx,num,th*2);
else update(idx,num,th*2+1);
pushup(th);
} int main()
{
int n,m,i,j,f,c,d;
while(scanf("%d%d%d",&n,&k,&m)!=EOF) //k=1的情况特殊考虑
{
if(k==1){
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(i=1;i<=m;i++){
scanf("%d",&f);
if(f==1){
scanf("%d%d",&c,&d);
}
else printf("1\n");
}
continue; } for(i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]--;
}
build(1,n,1);
for(i=1;i<=m;i++){
scanf("%d",&f);
if(f==1){
scanf("%d%d",&c,&d);
d--;
update(c,d,1);
}
else{
if(b[1].mindis>500000)printf("-1\n");
else printf("%d\n",b[1].mindis);
}
}
}
return 0;
}

zjnu1716 NEKAMELEONI (线段树)的更多相关文章

  1. 校内模拟赛T5:连续的“包含”子串长度( nekameleoni?) —— 线段树单点修改,区间查询 + 尺取法合并

    nekameleoni 区间查询和修改 给定N,K,M(N个整数序列,范围1~K,M次查询或修改) 如果是修改,则输入三个数,第一个数为1代表修改,第二个数为将N个数中第i个数做修改,第三个数为修改成 ...

  2. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  3. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  4. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  5. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  6. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  7. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  8. CF719E(线段树+矩阵快速幂)

    题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作 分析:线段树 线段树的每个节点表示(f[i],f[i-1])这 ...

  9. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

随机推荐

  1. 【Linux】rsync 守护进程的配置

    环境 centos7.2 1.首先查看是否安装rsync的相关包 rpm -qa | grep rsync rsync-3.1.2-4.el7.x86_64 如果没安装就yum install rsy ...

  2. C语言变量

    C语言变量 任何一种编程语言都离不开变量,特别是数据处理型程序,变量的使用非常频繁,没有变量参与程序甚至无法编制,即使编制运行后的意义也不大.变量之所以重要,是因为变量是编程语言中数据的符号标识和载体 ...

  3. DNS基础概要

    dns服务系统由客户端和服务器组成,提供域名到ip地址的解析,或者提供ip地址到域名的逆向解析. 1.DNS域名空间 每个dns域名由分级的label构成,如www.sina.com.cn,由www. ...

  4. BAPI_MATERIAL_BOM_GROUP_CREATE创建BOM

    天使用BAPI函数:BAPI_MATERIAL_BOM_GROUP_CREATE创建BOM组数据,过程中发现很多问题啊.总结如下: BOMGROUP        VARIANTS 这两个参数必须要传 ...

  5. Canal:同步mysql增量数据工具,一篇详解核心知识点

    老刘是一名即将找工作的研二学生,写博客一方面是总结大数据开发的知识点,一方面是希望能够帮助伙伴让自学从此不求人.由于老刘是自学大数据开发,博客中肯定会存在一些不足,还希望大家能够批评指正,让我们一起进 ...

  6. RocketMQ—消息队列入门

    消息队列功能介绍 字面上说的消息队列是数据结构中"先进先出"的一种数据结构,但是如果要求消除单点故障,保证消息传输可靠性,应对大流量的冲击,对消息队列的要求就很高了.现在互联网的& ...

  7. scrapy的大文件下载(基于一种形式的管道类实现)

    scrapy的大文件下载(基于一种形式的管道类实现) 爬虫类中将解析到的图片地址存储到item,将item提交给指定的管道 在管道文件中导包:from scrapy.pipelines.images ...

  8. JVM有哪些垃圾回收器

    JVM 的垃圾回收器 目录 JVM 的垃圾回收器 经典垃圾收集器 Serial 收集器 ParNew 收集器 Parallel Scavenge 收集器 Serial Old 收集器 Parallel ...

  9. 从零开始学spring源码之ioc预热:bean的拓展和beanProcessor注册

    上篇聊完了bean的解析,说起来做的事情很简单,把xml文件里面配置的标签全部解析到spring容器里面,但是spring做的时候,花了那么大代价去做,后面看看到底值不值得呢. 接下来看看prepar ...

  10. MySQL调优之分区表

    一.分区表的应用场景 1.为什么是用分区表? 表非常大以至于无法全部都放在内存中,或者只在表的最后部分有热点数据,其他均是历史数据,分区表是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理 ...