bzoj 4743: [Usaco2016 Dec]Robotic Cow Herd 线段树+二分答案

news/2024/10/18 2:29:17/

题意

有n个数集,每个数集里最多只有10个元素,现在从每个数集里面选数一个数,假设选出的数的和是p,给出k,问前k小的p的和。
n,k<=100000

分析

首先二分答案lim,然后考虑如何找到所有不大于lim的p的和。
设函数solve(num,kth)表示当前状态的和为num,上一次拓展的位置为kth。
用一颗线段树维护每个位置下一个选的数与上一个选的数的差的最小值,然后就在kth到n里面找到所有不大于lim-num的位置,那么这些位置都是可以拓展的。
当我们找到了超过k个数或者找完时就可以退出了。
总的复杂度是 O((n+k)logplogn) O ( ( n + k ) l o g p l o g n )
一开始打的是在每次在线段树的叶节点继续递归solve(),然后就被卡栈了。。。
接着改了改,每次先修改然后回溯完再修改回去,然后就超时了。。。
接下来就是各种卡常,卡了一晚上多终于被我卡了过去啦。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;typedef long long LL;const int N=100005;
const LL inf=(LL)1e15;int n,k,sz,pos,x,y,P;
LL sum,lim,a[N][15],val,LIM;
struct tree{LL mn;int id;}t[N*4];int read()
{int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}void updata(int d)
{while (d>1) d>>=1,t[d].mn=min(t[d<<1].mn,t[d<<1|1].mn);
}void build(int d,int l,int r)
{if (l==r) {t[d].id=1;t[d].mn=a[l][2]-a[l][1];return;}int mid=(l+r)>>1;build(d<<1,l,mid);build(d<<1|1,mid+1,r);t[d].mn=min(t[d<<1].mn,t[d<<1|1].mn);
}inline bool get(int d,int l,int r)
{if (l==r){pos=l;P=d;//int id=++t[d].id;t[d].mn=a[l][id+1]-a[l][id];return 1;}int mid=(l+r)>>1;if (x<=mid&&t[d<<1].mn<=LIM&&get(d<<1,l,mid)) return 1;return y>mid&&t[d<<1|1].mn<=LIM?get(d<<1|1,mid+1,r):0;
}void solve(LL num,int kth)
{sz++;sum+=num;int tmp=kth-1;x=tmp+1;y=n;LIM=lim-num;while (sz<k&&tmp<n&&get(1,1,n)){tmp=pos;int id=t[P].id;LL tmpnum=num,mn=t[P].mn;while (mn<=lim-tmpnum&&sz<k){tmpnum+=mn;id++;mn=a[tmp][id+1]-a[tmp][id];solve(tmpnum,tmp+1);}x=tmp+1;y=n;LIM=lim-num;}
}int main()
{n=read();k=read();LL num=0;for (int i=1;i<=n;i++){int tot=read();for (int j=1;j<=tot;j++) a[i][j]=read();sort(a[i]+1,a[i]+tot+1);num+=a[i][1];a[i][tot+1]=inf;}build(1,1,n);LL l=num,r=(LL)1e13;while (l<=r){lim=(l+r)>>1;sum=0;sz=0;solve(num,1);if (sz==k) r=lim-1;else l=lim+1;}sum=0;sz=0;lim=r;solve(num,1);printf("%lld",sum+(LL)(k-sz)*(r+1));return 0;
}

http://www.ppmy.cn/news/157620.html

相关文章

11g文档学习----sysdba sysoper OSDBA OSOPER

11 g Release 2 (11.2)》Supporting Documentation》Administrators Guide》 1 Getting Started with Database Administration SYSDBA and SYSOPER The following operations are authorized by the SYSDBA and SYSOPER system privileges: System Privilege Operations Au…

11G GI 安装同时跑脚本测试

问题&#xff1a;11G执行第二个脚本时间较长&#xff0c;测试两机器同时跑脚本 测试结果&#xff1a; 不能同时执行&#xff0c;必须依次执行&#xff0c;第二个脚本同时执行会因磁盘争夺导致失败&#xff1b; 第2个脚本先执行的节点&#xff0c;ASM SID将是第一个&#xff…

oracle杀掉pmon进程的影响,11g_测试kill杀死 background process后台进程与alert

----oracle后台进程 -bash-3.2$ ps -ef|grep ora_ oracle 4079 1 0 04:30 ? 00:00:05 ora_pmon_zxy oracle 4081 1 0 04:30 ? 00:00:03 ora_vktm_zxy oracle 4085 1 0 04:30 ? 00:00:01 ora_gen0_zxy oracle 4087 1 0…

ORACLE11G 性能调优学习

Oracle? Database 2 Day Performance Tuning Guide 11g Release 2 (11.2) E10822-04 重点需要掌握的工具 ADDM ASH ASSM Part I 一&#xff1a;调优工具 1、Oracle Database 11g Enterprise Edition 2、Oracle Enterprise Manager 3、Oracle Diagnostics Pack 4、Oracle Dia…

linux安装11g rac

&#xfeff;&#xfeff; 1、检查系统所需的软件包 rpm -qa | grep -E "binutils|compat-libstdc|elfutils-libelf|gcc|glibc|libaio|libgcc|libstdc|make|sysstat|unixODBC|pdksh" [roottestdb01 /]# rpm -qa | grep -E "binutils|compat-libstdc|elfutil…

Jzoj4743 积木

由于n很小(<15)我们考虑状态压缩 显然可以用三进制&#xff08;雾&#xff09;但是太浪费了 我们令f[i][j][s]表示现在已用的积木状态为S&#xff0c;最上面那个积木是第i个&#xff0c;其中这个积木的第j(0<j<3)条边是竖着的&#xff08;不在上表面&#xff09; 转移…

宏碁笔记本安装黑苹果过程记录

之前用这台笔记本装过Ubuntu&#xff0c;装过Deepin&#xff0c;今天继续折腾装一个黑苹果。 首先先做一个启动盘。我用的工具是Rufus&#xff0c;一款特别小众的软件&#xff0c;不过还是挺好用的。 image.png 然后就是写入镜像 image.png 镜像写入好之后插上电脑开机&#xf…

宏碁4743G+固态硬盘(SSD)+机械硬盘(HHD)混合用

原材料&#xff1a;&#xff08;某东上买的&#xff0c;二手东有个好处就是可以退货&#xff0c;开始买的某顿&#xff0c;评价貌似不太好&#xff0c;直接退货&#xff09; 三星理论上&#xff0c;SATA3接口能达到500M/S&#xff0c;可惜本本太老&#xff0c;只支持SATA2的了&…