题目

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的更多相关文章

  1. 【JZOJ5428】【NOIP2017提高A组集训10.27】查询

    题目 给出一个长度为n的序列a[] 给出q组询问,每组询问形如\(<x,y>\),求a序列的所有区间中,数字x的出现次数与数字y的出现次数相同的区间有多少个. 分析 我们可以维护一个前缀和 ...

  2. 5433. 【NOIP2017提高A组集训10.28】图

    题目描述 Description 有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x ...

  3. 【JZOJ5439】【NOIP2017提高A组集训10.31】Calculate

    题目 分析 对于\[\sum_{i=1}^{n}\lfloor\dfrac{T-B_i}{A_i}\rfloor\] 我们考虑拆开处理,得到 \[\sum_{i=1}^{n}(\lfloor\dfra ...

  4. 【JZOJ5430】【NOIP2017提高A组集训10.27】图

    题目 有一个n个点的无向图,给出m条边,每条边的信息形如\(<x,y,c,r>\) 给出q组询问形如\(<u,v,l,r>\) 接下来解释询问以及边的意义 询问表示,一开始你在 ...

  5. 5432. 【NOIP2017提高A组集训10.28】三元组

    题目 题目大意 给你\(X+Y+Z\)个三元组\((x_i,y_i,z_i)\). 然后选\(X\)个\(x_i\),选\(Y\)个\(y_i\),选\(Z\)个\(z_i\). 每个三元组只能选择其 ...

  6. [JZOJ 5437] [NOIP2017提高A组集训10.31] Sequence 解题报告 (KMP)

    题目链接: http://172.16.0.132/senior/#main/show/5437 题目: 题解: 发现满足上述性质并且仅当A序列的子序列的差分序列与B序列的差分序列相同 于是我们把A变 ...

  7. 【JZOJ5434】【NOIP2017提高A组集训10.30】Matrix

    题目 分析 假设答案为ans, 发现\[k=\sum_{i=1}^{min(n,k)}\lfloor \dfrac{ans}{i} \rfloor\] 于是可以对ans进行二分, 用分块来求出上面的式 ...

  8. 【NOIP2017提高A组模拟10.7】Adore

    题目 小w 偶然间见到了一个DAG. 这个DAG 有m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k 个节点. 现在小w 每次可以取反第i(1 < i < n - 1) ...

  9. NOIP2017提高A组模拟10.6】Biology

    题目 trie 暴力就是对于每个询问的T个字符串 第i个和第i+1个直接个从后暴力枚举每位是否相同, 但这个方法TLE 我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀. 我们把所有的字符串 ...

随机推荐

  1. aws 预留实例到期监控

    环境准备 安装python的aws 开发工具包 pip install boto3 配置aws账号 [root@zabbix service]# aws configure AWS Access Ke ...

  2. Partition to K Equal Sum Subsets

    Given an array of integers nums and a positive integer k, find whether it's possible to divide this ...

  3. WijmoJS 以声明方式添加 Vue 菜单项

    WijmoJS 以声明方式添加 Vue 菜单项 在V2019.0 Update2 的全新版本中,Vue框架下 WijmoJS 的前端UI组件功能得到再度增强. 如今,向wj菜单组件添加项的方法将不限于 ...

  4. HTTP协议 django下载安装 url路由分发

    今日内容 HTTP协议 MVC和MTV框架模式 django下载安装 django的url路由分发 HTTP协议 http协议 请求信息格式 GET / HTTP/1.1 请求行 Host: 127. ...

  5. MySQL性能优化(一):优化方式

    原文:MySQL性能优化(一):优化方式 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/v ...

  6. C# 面向对象4 构造函数

    构造函数 1.构造函数用来创建对象,并且可以在构造函数中对对象进行初始化. (给对象的每个属性依次的赋值) 2.构造函数是用来创建对象的特殊方法: 1.方法名和类名一样. 2.没有返回值,连void都 ...

  7. python:map 函数

    map(func, *iterables) --> map object map()是 Python 内置的高阶函数,它接收一个函数 func 和一个 list(*iterables),并通过把 ...

  8. 二、redis学习(java操作redis缓存的工具jedis)

  9. 淘宝flexible.js的使用

    首先大家最关注的怎么使用,原理不原理是后面的事 比如设计稿量来的宽度是100px 那么我们布局的时候,就这么写{width:1.3333rem},1.3333rem是由100/75算出来的,以此类推2 ...

  10. python 定义变量

    定义变量 什么是变量? 在程序运行过程中,其值可以改变的量 标识符(命令规范) 只能由数字.字母.下划线组成 不能以数字开头 不能是系统关键字 # 导入包import keyword​# 打印所有关键 ...