【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 我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀. 我们把所有的字符串 ...
随机推荐
- aws 预留实例到期监控
环境准备 安装python的aws 开发工具包 pip install boto3 配置aws账号 [root@zabbix service]# aws configure AWS Access Ke ...
- 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 ...
- WijmoJS 以声明方式添加 Vue 菜单项
WijmoJS 以声明方式添加 Vue 菜单项 在V2019.0 Update2 的全新版本中,Vue框架下 WijmoJS 的前端UI组件功能得到再度增强. 如今,向wj菜单组件添加项的方法将不限于 ...
- HTTP协议 django下载安装 url路由分发
今日内容 HTTP协议 MVC和MTV框架模式 django下载安装 django的url路由分发 HTTP协议 http协议 请求信息格式 GET / HTTP/1.1 请求行 Host: 127. ...
- MySQL性能优化(一):优化方式
原文:MySQL性能优化(一):优化方式 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/v ...
- C# 面向对象4 构造函数
构造函数 1.构造函数用来创建对象,并且可以在构造函数中对对象进行初始化. (给对象的每个属性依次的赋值) 2.构造函数是用来创建对象的特殊方法: 1.方法名和类名一样. 2.没有返回值,连void都 ...
- python:map 函数
map(func, *iterables) --> map object map()是 Python 内置的高阶函数,它接收一个函数 func 和一个 list(*iterables),并通过把 ...
- 二、redis学习(java操作redis缓存的工具jedis)
- 淘宝flexible.js的使用
首先大家最关注的怎么使用,原理不原理是后面的事 比如设计稿量来的宽度是100px 那么我们布局的时候,就这么写{width:1.3333rem},1.3333rem是由100/75算出来的,以此类推2 ...
- python 定义变量
定义变量 什么是变量? 在程序运行过程中,其值可以改变的量 标识符(命令规范) 只能由数字.字母.下划线组成 不能以数字开头 不能是系统关键字 # 导入包import keyword# 打印所有关键 ...