【NOIP2017提高A组集训10.21】Fantasy
题目
Y sera 陷入了沉睡,幻境中它梦到一个长度为N 的序列{Ai}。
对于这个序列的每一个子串,定义其幻境值为这个子串的和,现在Y sera 希望选择K 个不同的子串并使得这K 个子串的幻境值之和最大。
然而由于梦境中的种种限制,这些子串的长度必须在L 到R 之间。
你需要告诉她,最大的幻境值之和。
分析
题目要求求出最大的和,那显然就是找出最大的k个子串。
考虑怎么找出最大的k个子串。
我们求一次前缀和,扔进一个可持久化权值线段树上。
然后二分第k大的子串的值mid,枚举子串的开头,对于第i个开头,查询第i+L-1到i+R-1棵权值线段树上子串值大于等于mid的个数。
将大于等于mid的子串总个数与k比较进行二分。
最后用线段树将大于等于二分出来的值的子串的值加起来就是答案。
时间复杂度O(NlogN)。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
const int maxlongint=2147483647;
const int mo=1e9;
const int N=100005;
const int M=10000;
using namespace std;
struct tree
{
int l,r,num;
long long sum;
}tr[N*50];
int a[N],n,k,L,R,rt[N],tot;
long long ans;
int max(int x,int y)
{
return x>y?x:y;
}
int min(int x,int y)
{
return x<y?x:y;
}
void put(int v,int l,int r,int x)
{
tr[v].num++;
tr[v].sum+=1ll*x;
if(l==r) return;
int mid=(1ll*l+r)>>1;
if(x<=mid) tr[++tot]=tr[tr[v].l],tr[v].l=tot,put(tr[v].l,l,mid,x);
else tr[++tot]=tr[tr[v].r],tr[v].r=tot,put(tr[v].r,mid+1,r,x);
}
long long find1(int v,int v1,int l,int r,long long x,int y,int t)
{
if(v==0 || x>y) return 0;
if(l==x && r==y)
{
if(!t) return tr[v].num-tr[v1].num;
else return tr[v].sum-tr[v1].sum;
}
int mid=(1ll*l+r)>>1;
if(y<=mid) return find1(tr[v].l,tr[v1].l,l,mid,x,y,t);
else
if(x>mid) return find1(tr[v].r,tr[v1].r,mid+1,r,x,y,t);
else return find1(tr[v].l,tr[v1].l,l,mid,x,mid,t)+find1(tr[v].r,tr[v1].r,mid+1,r,mid+1,y,t);
}
int main()
{
scanf("%d%d%d%d",&n,&k,&L,&R);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=a[i-1];
a[0]=mo;
for(int i=1;i<=n;i++)
a[i]+=mo,rt[i]=++tot,tr[rt[i]]=tr[rt[i-1]],put(rt[i],0,mo*2,a[i]);
int l=0,r=mo*2;
while(l+1<r)
{
int mid=(1ll*l+r)>>1,cnt=0;
for(int i=1;i<=n && i+L-2<n;i++) cnt=cnt+find1(rt[min(i+R-1,n)],rt[i+L-2],0,mo*2,max(a[i-1]+mid-mo,0),mo*2,0);//-find(rt[i+L-2],0,mo*2,max(a[i-1]+mid-mo,0),mo*2,0);
if(cnt>=k) l=mid;
else r=mid;
}
long long cnt=0;
ans=0;
for(int i=1;i<=n && i+L-2<n;i++)
{
int wz=find1(rt[min(i+R-1,n)],rt[i+L-2],0,mo*2,max(a[i-1]+r-mo,0),mo*2,0);
cnt=cnt+wz;
ans=ans+find1(rt[min(i+R-1,n)],rt[i+L-2],0,mo*2,max(a[i-1]+r-mo,0),mo*2,1)-1ll*wz*a[i-1];
}
if(cnt>=k)
{
ans-=(cnt-1ll*k)*(r-mo);
printf("%lld",ans);
return 0;
}
ans=cnt=0;
for(int i=1;i<=n && i+L-2<n;i++)
{
int wz=find1(rt[min(i+R-1,n)],rt[i+L-2],0,mo*2,max(a[i-1]+l-mo,0),mo*2,0);
cnt=cnt+wz;
ans=ans+find1(rt[min(i+R-1,n)],rt[i+L-2],0,mo*2,max(a[i-1]+l-mo,0),mo*2,1)-1ll*wz*a[i-1];
}
ans-=(cnt-1ll*k)*(l-mo);
printf("%lld",ans);
}
【NOIP2017提高A组集训10.21】Fantasy的更多相关文章
- 【JZOJ5428】【NOIP2017提高A组集训10.27】查询
题目 给出一个长度为n的序列a[] 给出q组询问,每组询问形如\(<x,y>\),求a序列的所有区间中,数字x的出现次数与数字y的出现次数相同的区间有多少个. 分析 我们可以维护一个前缀和 ...
- 5433. 【NOIP2017提高A组集训10.28】图
题目描述 Description 有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x ...
- 【JZOJ5439】【NOIP2017提高A组集训10.31】Calculate
题目 分析 对于\[\sum_{i=1}^{n}\lfloor\dfrac{T-B_i}{A_i}\rfloor\] 我们考虑拆开处理,得到 \[\sum_{i=1}^{n}(\lfloor\dfra ...
- 【JZOJ5430】【NOIP2017提高A组集训10.27】图
题目 有一个n个点的无向图,给出m条边,每条边的信息形如\(<x,y,c,r>\) 给出q组询问形如\(<u,v,l,r>\) 接下来解释询问以及边的意义 询问表示,一开始你在 ...
- 5432. 【NOIP2017提高A组集训10.28】三元组
题目 题目大意 给你\(X+Y+Z\)个三元组\((x_i,y_i,z_i)\). 然后选\(X\)个\(x_i\),选\(Y\)个\(y_i\),选\(Z\)个\(z_i\). 每个三元组只能选择其 ...
- [JZOJ 5437] [NOIP2017提高A组集训10.31] Sequence 解题报告 (KMP)
题目链接: http://172.16.0.132/senior/#main/show/5437 题目: 题解: 发现满足上述性质并且仅当A序列的子序列的差分序列与B序列的差分序列相同 于是我们把A变 ...
- 【JZOJ5434】【NOIP2017提高A组集训10.30】Matrix
题目 分析 假设答案为ans, 发现\[k=\sum_{i=1}^{min(n,k)}\lfloor \dfrac{ans}{i} \rfloor\] 于是可以对ans进行二分, 用分块来求出上面的式 ...
- 【NOIP2017提高A组模拟10.7】Adore
题目 小w 偶然间见到了一个DAG. 这个DAG 有m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k 个节点. 现在小w 每次可以取反第i(1 < i < n - 1) ...
- NOIP2017提高A组模拟10.6】Biology
题目 trie 暴力就是对于每个询问的T个字符串 第i个和第i+1个直接个从后暴力枚举每位是否相同, 但这个方法TLE 我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀. 我们把所有的字符串 ...
随机推荐
- 【神经网络与深度学习】Caffe Model Zoo许多训练好的caffemodel
Caffe Model Zoo 许多的研究者和工程师已经创建了Caffe模型,用于不同的任务,使用各种种类的框架和数据.这些模型被学习和应用到许多问题上,从简单的回归到大规模的视觉分类,到Siames ...
- inner join on会过滤掉两边空值的条件
前两天工作过程中,遇到一个问题,关于join on查询的,对于查出来的结果一直都很疑惑,这里记录一下. 1.首先看下面这条sql查询语句: 查询出来的结果是25053 2.加个 o.lat = n.l ...
- 【Linux 网络编程】REUSADDR
(1)服务器端尽可能使用REUSEADDR.(2)在绑定之前尽可能调用setsockopt来设置REUSEADDR套接字选项.(3)使用REUSEADDR选项可以使得不必等待TIME_WAIT状态消失 ...
- Longest Palindromic Subsequence
Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...
- 02-Zookeeper介绍及安装
1 Zookeeper介绍 ZooKeeper是为分布式应用所设计的高可用.高性能且一致的开源协调服务,它提供了一项基本服务:分布式锁服务.分布式应用可以基于它实现更高级的服务,实现诸如同步服务.配置 ...
- MateBook 换内存条
欢迎关注微信公众号:猫的尾巴有墨水 为啥要拆MateBook D笔记本? 最近这个Windows 10更新后,内存暴增,每次禁用windows update和同步服务模块后,依然不能彻底解决内存爆炸的 ...
- 你写的 Java 代码是如何一步步输出结果的? (转)
出处: 一步步解析java执行内幕 对于任何一门语言,要想达到精通的水平,研究它的执行原理(或者叫底层机制)不失为一种良好的方式.在本篇文章中,将重点研究java源代码的执行原理,即从程 序员编写J ...
- Java8 parallelStream浅析
JAVA8中引入了lamda表达式和Stream接口.其丰富的API及强大的表达能力极大的简化代码,提升了效率,同时还通过parallelStream提供并发操作的支持,本文探讨parallelStr ...
- QVector与QMap查找效率实战(QMap快N倍,因为QVector是数组,QMap是有序二叉树,查找的时候是N和LogN的速度对比)
因为项目使用QVector,太慢了,听说QMap比QVector查找时快,所以写一个小程序试试: 从30000个数据中找5000个 程序运行截图如下: QVector QMap 一样的数据,找一样的数 ...
- ASP.Net Core下Authorization的几种方式 - 简书
原文:ASP.Net Core下Authorization的几种方式 - 简书 ASP.Net Core下Authorization的几种方式 Authorization其目标就是验证Http请求能否 ...