相当于求满足在子段中出现的颜色只在该子段中出现的非空子段数量。这也就相当于其中出现的颜色最左出现的位置在左端点右侧,最右出现的位置在右端点左侧。那么若固定某个端点,仅考虑对该端点的限制,会有一段合法区间。这个区间可以二分+st表求出。于是枚举右端点,在其合法区间内查询有多少个合法左端点(即合法区间包括该右端点),上主席树即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,a[N],root[N],head[N],tail[N],l[N],r[N],f[N][],lg2[N],cnt;
struct data{int l,r,x;
}tree[N<<];
int query(int l,int r)
{
if (l>r) return N;
return min(f[l][lg2[r-l+]],f[r-(<<lg2[r-l+])+][lg2[r-l+]]);
}
int query2(int l,int r)
{
if (l>r) return -;
return max(f[l][lg2[r-l+]],f[r-(<<lg2[r-l+])+][lg2[r-l+]]);
}
void ins(int &k,int l,int r,int x)
{
tree[++cnt]=tree[k],k=cnt;tree[k].x++;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(tree[k].l,l,mid,x);
else ins(tree[k].r,mid+,r,x);
}
int query(int x,int y,int l,int r,int p,int q)
{
if (!y) return ;
if (l==p&&r==q) return tree[y].x-tree[x].x;
int mid=l+r>>;
if (q<=mid) return query(tree[x].l,tree[y].l,l,mid,p,q);
else if (p>mid) return query(tree[x].r,tree[y].r,mid+,r,p,q);
else return query(tree[x].l,tree[y].l,l,mid,p,mid)+query(tree[x].r,tree[y].r,mid+,r,mid+,q);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5011.in","r",stdin);
freopen("bzoj5011.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
while (T--)
{
n=read();
for (int i=;i<=n;i++) a[i]=read(),head[i]=n+,tail[i]=;
for (int i=;i<=n;i++) head[a[i]]=min(head[a[i]],i),tail[a[i]]=max(tail[a[i]],i);
lg2[]=;
for (int i=;i<=n;i++)
{
lg2[i]=lg2[i-];
if ((<<lg2[i])<=i) lg2[i]++;
}
for (int i=;i<=n;i++) f[i][]=head[a[i]];
for (int j=;j<;j++)
for (int i=;i<=n;i++)
f[i][j]=min(f[i][j-],f[min(n,i+(<<j-))][j-]);
for (int i=;i<=n;i++)
{
int L=i-,R=n;
while (L<=R)
{
int mid=L+R>>;
if (query(i,mid)>=i) l[i]=mid,L=mid+;
else R=mid-;
}
}
for (int i=;i<=n;i++) f[i][]=tail[a[i]];
for (int j=;j<;j++)
for (int i=;i<=n;i++)
f[i][j]=max(f[i][j-],f[min(n,i+(<<j-))][j-]);
for (int i=;i<=n;i++)
{
int L=,R=i+;
while (L<=R)
{
int mid=L+R>>;
if (query2(mid,i)<=i) r[i]=mid,R=mid-;
else L=mid+;
}
}
root[]=;
for (int i=;i<=n;i++)
{
root[i]=root[i-];
ins(root[i],,n,l[i]);
}
ll ans=;
for (int i=;i<=n;i++)
ans+=query(root[r[i]-],root[i],,n,i,n);
printf(LL,ans);
}
return ;
}

BZOJ5011 JXOI2017颜色(主席树)的更多相关文章

  1. BZOJ5011 [JXOI2017]颜色 【线段树 + 主席树】

    题目链接 BZOJ5011 题解 一定只有我这种智障会用这么奇怪的方法做这道题.. 由题我们知道最后剩余的一定是一个区间,而且区间内的颜色不存在于区间外 所以我们的目的就是为了找到这样的区间的数量 区 ...

  2. [BZOJ5011][JXOI2017]颜色

    5011: [Jx2017]颜色 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 84  Solved: 46[Submit][Status][Disc ...

  3. 洛谷P4065 [JXOI2017]颜色(线段树)

    题意 题目链接 Sol 线段树板子题都做不出来,真是越来越菜了.. 根据题目描述,一个合法区间等价于在区间内的颜色没有在区间外出现过. 所以我们可以对于每个右端点,统计最长的左端点在哪里,刚开始以为这 ...

  4. [JXOI2017]颜色 线段树扫描线 + 单调栈

    ---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们 ...

  5. [四校联考P3] 区间颜色众数 (主席树)

    主席树 Description 给定一个长度为 N 颜色序列A,有M个询问:每次询问一个区间里是否有一种颜色的数量超过了区间的一半,并指出是哪种颜色. Input 输入文件第一行有两个整数:N和C 输 ...

  6. 2018.07.07 洛谷 P3939 数颜色(主席树)

    P3939 数颜色 题目背景 大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg 题目描述 小 C 的兔子不是雪白的,而是五彩缤纷的.每只兔子都有一种颜色,不 ...

  7. bzoj2120: 数颜色(BIT套主席树+set/分块)

    带修改的 HH的项链. 带修改考虑用BIT套主席树,查区间里有几个不同的数用a[i]上次出现的位置pre[i]<l的数有几个来算就好了. 考虑怎么修改.修改i的时候,我们需要改变i同颜色的后继的 ...

  8. 主席树 STL+二分【p3939】数颜色

    Description 小 C 的兔子不是雪白的,而是五彩缤纷的.每只兔子都有一种颜色,不同的兔子可能有 相同的颜色.小 C 把她标号从 \(1\) 到 \(n\) 的 \(n\) 只兔子排成长长的一 ...

  9. BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P ...

随机推荐

  1. Easyui 控件的初始化方法

    问题: Easyui的控件在初始化的时候有两种方式: 页面指定class属性 js里初始化该id为easyui的控件 那么问题是: 如果页面不指定class属性,只是使用js初始化的话,会导致无法用控 ...

  2. 自己用C语言写RL78 serial bootloader

    了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 之前用C实现过多款PI ...

  3. 简单读取 properties文件

    看了网上很多读取的方法,都太过复杂,直接使用下面的方法就可以简单读取 properties文件了 ide使用idea 测试读取成功 import java.util.ResourceBundle; p ...

  4. 探寻ASP.NET MVC鲜为人知的奥秘(2):与Entity Framework配合,让异步贯穿始终

    Why 在应用程序,尤其是互联网应用程序中,性能一直是很多大型网站的困扰,由于Web2.0时代的到来,人们更多的把应用程序从C/S结构迁移到B/S结构,这样会带来客户端轻量,部署.试试方便快捷等优势, ...

  5. 基于Spring的最简单的定时任务实现与配置(三)--番外篇 cron表达式的相关内容

    本来这篇文章是会跟本系列的前两篇文章一起发布的.但是,昨天在找资料总结的时候遇到了一点意外,就延后了一些. 本篇的内容主要参考了 这篇博文:http://www.cnblogs.com/junrong ...

  6. 原生js使用ajax

    AJAX 可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容(默认是异步) (1)使用ajax会用到XMLHttpRequest()对象 (2)然后使用open方法定义请求方法和请求 ...

  7. LeeCode_01_Two sum

    Two Sum Given an array of integers, return indices of the two numbers such that they add up to a spe ...

  8. 实现短信超链接调起APP

    因APP推广的需求,需要给APP用户定期发送短信提醒登录使用,为了更好的用户体验在短信内容中嵌入了可以直接打开APP的超链接,下面介绍一下具体的代码实现. 编辑openApp.html文件: < ...

  9. [CF1137]Museums Tour

    link \(\text{Description:}\) 一个国家有 \(n\) 个城市,\(m\) 条有向道路组成.在这个国家一个星期有 \(d\) 天,每个城市有一个博物馆. 有个旅行团在城市 \ ...

  10. Python基础灬dict&set

    字典dict 字典使用键-值(key-value)存储,具有极快的查找速度. dict基本操作 取值 a_dict = {'name': 'jack', 'age': 18} print(a_dict ...