【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 我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀. 我们把所有的字符串 ...
随机推荐
- 【Linux开发】linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write
linux设备驱动归纳总结(三):2.字符型设备的操作open.close.read.write 一.文件操作结构体file_operations 继续上次没讲完的问题,文件操作结构体到底是什么东西, ...
- Elasticsearch-更新现有文档
ES-更新现有文档 ES的更新API允许发送文档所需要做的修改,而且API会返回一个答复,告知操作是否成功.更新流程如下 1. 检索现有的文档.为了使这步奏效,必须打开_source字段,否则ES并不 ...
- 最长相同01数的子串(map搞搞)--牛客第三场 -- Crazy Binary String
题意: 如题. 或者用我的数组分治也可以,就是有点愚蠢. //#include <bits/stdc++.h> #include <map> #include <iost ...
- 设置队列中文件上的“X”号的点击事件+uploadLimit动态加1
目的:1.设置文件队列中“x”号的点击事件 2.每次删除服务器文件后,把uploadLimit + 1: 'onUploadSuccess': function (file, data, respon ...
- 常用的TCP/UDP端口
已知的TCP/UDP端口可以在wikipedia上找到: List of TCP and UDP port numbers, 太多了,按组列举了最常用的,如下: FTP:21SSH:22Telnet: ...
- php 中php-fpm工作原理
1.CGI 是服务器与后台语言交互的协议,有了这个协议,开发者可以使用任何语言处理服务器转发过来的请求,动态地生成内容, 保证了传递过来的数据是标准格式的(规定了以什么样的格式传哪些数据(URL.查询 ...
- ccs之经典布局(二)(两栏,三栏布局)
接上篇ccs之经典布局(一)(水平垂直居中) 四.两列布局 单列宽度固定,另一列宽度是自适应. 1.float+overflow:auto; 固定端用float进行浮动,自适应的用overflow:a ...
- LLVM4.0与3.5编译phase对比
说是LLVM4.0和3.5的对比,其实是Clang的4和3.5的对比.在调试Clang编译源码的过程中,发现-S选项在4.0和3.5中的处理不一样,后来使用命令验证了这个事情 jourluohua@j ...
- Java 计算两点间的全部路径(二)
一.有向线段,存储开始点与结束点 /** * 有方向的线段 * * @author Gm * */ public class DirectionLine implements Cloneable { ...
- Swift(一)语言介绍
Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题. Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在其中 ...