bzoj 5110 Yazid的新生舞会
题目大意:
一个数列,求有多少个区间$[l,r]$满足该区间的众数出现次数大于$\lceil \frac{r-l}{2} \rceil$
思路:
对于一个区间满足条件的众数明显是唯一的 所以设该数的前缀和数组为$S$
则一个区间$(l,r]$满足条件满足$2 \times (S_r-S_l)>(r-l)$ 移项后得到$2 \times S_r-r>2 \times S_l-l$
则对于$2 \times S_i-i$建立函数发现该函数由斜率为$\pm 1$组成
所有函数的关键点总数为$n$ 对于$y$轴建立权值线段树 发现中间连续的一段的贡献为一次函数
写一波一次函数即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define rep(i,s,t) for(register int i=(s),i__end=(t);i<=i__end;++i)
#define dwn(i,s,t) for(register int i=(s),i__end=(t);i>=i__end;++i)
#define ren(x) for(register int i=fst[x];i;i=nxt[i])
#define pb(a,x) vec[a].push_back(x);
#define ll long long
#define inf 2139062143
#define MAXN 1001000
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,N,tp,g[MAXN],hsh[MAXN],m,tagk[MAXN<<],tagb[MAXN<<];
ll sum[MAXN<<],ans;
vector <int> vec[MAXN];
inline ll calc(ll k,ll b,int x,int y) {return ((ll)((ll)k*y+k*x+*b)*((ll)y-x+))/;}
void pshd(int k,int l,int r,int mid)
{
sum[k<<]+=calc(tagk[k],tagb[k],l,mid);
sum[k<<|]+=calc(tagk[k],tagb[k],mid+,r);
tagk[k<<]+=tagk[k],tagk[k<<|]+=tagk[k],tagb[k<<]+=tagb[k],tagb[k<<|]+=tagb[k];
tagk[k]=tagb[k]=0LL;
}
void mdf(int k,int l,int r,int a,int b,ll d,ll t)
{
if(l==a&&r==b) {tagb[k]+=t,tagk[k]+=d,sum[k]+=calc(d,t,l,r);return ;}
int mid=l+r>>;if(tagb[k]!=||tagk[k]!=) pshd(k,l,r,mid);
if(b<=mid) mdf(k<<,l,mid,a,b,d,t);else if(a>mid) mdf(k<<|,mid+,r,a,b,d,t);
else {mdf(k<<,l,mid,a,mid,d,t);mdf(k<<|,mid+,r,mid+,b,d,t);}
sum[k]=sum[k<<]+sum[k<<|];
}
ll query(int k,int l,int r,int a,int b)
{
if(l==a&&r==b) return sum[k];
int mid=l+r>>;if(tagb[k]!=||tagk[k]!=) pshd(k,l,r,mid);
if(b<=mid) return query(k<<,l,mid,a,b);
else if(a>mid) return query(k<<|,mid+,r,a,b);
else return query(k<<,l,mid,a,mid)+query(k<<|,mid+,r,mid+,b);
}
void work(int x)
{
int t,las=,pos;rep(i,,vec[x].size()-)
{
t=vec[x][i],pos=las-(t-vec[x][i-])+;
ans+=query(,,N,pos+n,las+n);
mdf(,,N,pos+n+,las+n+,,-pos-n);
if(las+n+<=N) mdf(,,N,las+n+,N,,las-pos+);
las=pos+;
}
las=;rep(i,,vec[x].size()-)
{
t=vec[x][i],pos=las-(t-vec[x][i-])+;
mdf(,,N,pos+n+,las+n+,-,pos+n);
if(las+n+<=N) mdf(,,N,las+n+,N,,pos-las-);
las=pos+;
}
}
int main()
{
n=read(),N=(n<<)+,tp=read();rep(i,,n) {g[i]=read();if(!hsh[g[i]]) hsh[g[i]]=++m;}
rep(i,,m) pb(i,);rep(i,,n) pb(hsh[g[i]],i);rep(i,,m) pb(i,n+);
rep(i,,m) work(i);printf("%lld\n",ans);
}
bzoj 5110 Yazid的新生舞会的更多相关文章
- 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会 线段树
[BZOJ5110][CodePlus2017]Yazid 的新生舞会 Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一 ...
- bzoj5110: [CodePlus2017]Yazid 的新生舞会
Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一个子区间[l,r] ,如果该子区间内的众数在该子区间的出现次数严格大于( ...
- [loj 6253] Yazid的新生舞会
(很久之前刷的题现在看起来十分陌生a) 题意: 给你一个长度为n的序列A,定义一个区间$[l,r]$是“新生舞会的”当且仅当该区间的众数次数严格大于$\frac{r-l+1}{2}$,求有多少子区间是 ...
- [BZOJ 4819] [SDOI 2017] 新生舞会
Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴. 有 \(n\) 个男生和 \(n\) 个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴. C ...
- 【bzoj5110】Yazid的新生舞会
这里是 $THUWC$ 选拔时间 模拟赛的时候犯 $SB$ 了,写了所有的部分分,然后直接跑过了 $4$ 个大样例(一个大样例是一个特殊情况)…… 我还以为我非常叼,部分分都写对了,于是就不管了…… ...
- BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)
LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...
- 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会
题解: 没笔的时候我想了一下 发现如果不是出现一半次数而是k次,并不太会做 然后我用前缀和写了一下发现就是维护一个不等式: 于是就可以随便维护了
- 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)
学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2 ...
- 【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap
题目描述 求一个序列所有的子区间,满足区间众数的出现次数大于区间长度的一半. 输入 第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型.数据类型的作用将在子任务中说明. 第二行n个用 ...
随机推荐
- iOS上线check_list
iOS 上线前 check_list 类型 序号 检查项 结果(pass/no) 安装 卸载 1 非越狱环境下的安装.卸载 2 越狱环境下的安装.卸载 3 安装文件检查,无泄漏用户信息的隐患 4 卸载 ...
- MySQL常用函数使用示例
#从指定字符中,随机生成12位字符select substring('0123456789abcdefghijklmnopqrstuvwxyz',floor(0+RAND()*36),12); #显示 ...
- kettle数据同步方法
1.实时性要求不高,采用全删全插的方式(适合于维度表.大数据量表) 2.有时间维度,直接从事实表同步的数据,可以采用根据时间字段进行筛选,增量同步.这个网上有很多例子,就不重复写了. 3.没有时间维度 ...
- 洛谷 P1009 阶乘之和
题目描述 用高精度计算出S=1!+2!+3!+…+n!(n≤50) 其中“!”表示阶乘,例如:5!=5*4*3*2*1. 输入输出格式 输入格式: 一个正整数N. 输出格式: 一个正整数S,表示计算结 ...
- Android计算器简单逻辑实现
Android计算器简单逻辑实现 引言: 我的android计算器的实现方式是:按钮输入一次,就处理一次. 但是如果你学过数据结构(栈),就可以使用表达式解析(前缀,后缀)处理. 而这个方式已经很成熟 ...
- 用dfs求联通块(UVa572)
一.题目 输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块.如果两个字符所在的格子相邻(横.竖.或者对角线方向),就说它们属于同一个八连块. 二.解题思路 和前面的二叉树遍历类似,图也有DF ...
- atom 自定义快捷键
'atom-text-editor': 'shift-alt-i':'core:move-up' 'shift-alt-space':'core:move-down' 'shift-alt-l':'c ...
- 模板类 vector
概要 介绍一下模板类 vector 的常用操作,以及一个应用举例,顺时针打印矩阵. 基本定义 模板类 vector 是一种动态数组,它是使用 new 创建动态数组的替代品,实际上,vector 也 ...
- shell脚本,awk实现行列转换
[root@localhost study]# cat file 张三 语文 张三 数学 李四 语文 李四 数学 王五 语文 王五 数学 王五 英语 怎么实现为下面的排序??? 语文 数学 语文 数学 ...
- MySQL丨01丨数据库基本概念
以前记录数据可能很少也很简单,比如说老王借了老李半斤肉,这样的数据老李直接就写到墙上就行了. 后来数据多了人们就以表格的方式开始记录,写到一张A4纸上,比如学生的档案,有表头和序号等. 表头里有姓名. ...