【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 我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀. 我们把所有的字符串 ...
随机推荐
- Java十大bug之——包冲突
找bug就像破案,有的bug简单,有的bug复杂,还有的bug隐藏的令人难以发现. 一个逻辑上看起来一切都正常,结果确有问题,且怎么分析都感觉自己写的没问题的情况——包冲突 遇到这个bug最开始没有任 ...
- 阿里云Open API自动化脚本—ECS公网IP转化弹性公网IP
1.OpenAPI Explorer 记录一下使用阿里云 Open API 自动化/脚本化 “ECS 公网 IP 转化弹性公网 IP”的实现 全过程.原博客地址:https://www.markedi ...
- 【pytorch】学习笔记(三)-激励函数
[pytorch]学习笔记-激励函数 学习自:莫烦python 什么是激励函数 一句话概括 Activation: 就是让神经网络可以描述非线性问题的步骤, 是神经网络变得更强大 1.激活函数是用来加 ...
- 2018.08.14【2018提高组】模拟A组 比赛总结
题解 这次的A组难得得水. T1 这题我一看,就想起了GDOI的一道题--密码锁 \(O(n)\)算法--差分 于是乎兴奋地发现这道题可以用差分来解. 设\(f_i=a_i-a_{i-1}\). 然后 ...
- Java中创建的对象多了,必然影响内存和性能
1, Java中创建的对象多了,必然影响内存和性能,所以对象的创建越少越好,最后还要记得销毁.
- python中super函数的参考
https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ http://wiki.jikexueyuan.com/proj ...
- 了解MyISAM与InnoDB的索引差异(转)
出处原文: 1分钟了解MyISAM与InnoDB的索引差异 数据库的索引分为主键索引(Primary Inkex)与普通索引(Secondary Index).InnoDB和MyISAM是怎么利用B+ ...
- vue-router和webpack懒加载,页面性能优化篇
在vue单页应用中,当项目不断完善丰富时,即使使用webpack打包,文件依然是非常大的,影响页面的加载.如果我们能把不同路由对应的组件分割成不同的代码块,当路由被访问时才加载对应的组件(也就是按需加 ...
- 如何在万亿级别规模的数据量上使用Spark
一.前言 Spark作为大数据计算引擎,凭借其快速.稳定.简易等特点,快速的占领了大数据计算的领域.本文主要为作者在搭建使用计算平台的过程中,对于Spark的理解,希望能给读者一些学习的思路.文章内容 ...
- 27 Python 装饰器
一. 我们先写一个玩游戏的步骤 # def play(): # print("双击LOL") # print("选择狂战士") # print("进草 ...