【CF 678F】Lena and Queries
Time Limit: 2000 ms Memory Limit: 512 MB
Description
初始有一个空集合
n个操作
有三种操作,如下:
1 a b 表示向集合中插入二元组(a,b)
2 i 表示删除第i次操作时所插入的二元组
3 q 表示询问当前集合的二元组中,$(a*q+b)$最大是多少
Input
第一行一个整数$n$,表示操作个数
接下来$n$行,每行表示一个操作,格式见上
Output
对于每个询问输出一行表示最大值
如果询问时集合为空,输出 EMPTY SET
Sample Input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1
Sample Output
EMPTY SET
5
99
5
Hint
对于操作$2~i$,数据保证第$i$次操作的类型为$1$,且之前未被删除,且不会删除仍未进行的操作
对于$10\%$的数据,$1\le n\le 5000$
对于$30\%$的数据,$1\le n\le 50000$
对于$100\%$的数据,$1\le n\le 3*10^5,~~-10^9\le a,b,q\le 10^9$
题解
先考虑点集不变的情况:
我们设$x=q*a+b$,那么目标就是在集合中找到最大的$k$。
移一下项:$b=-q*a+x$,现在的目标变为,对于每一个$(a,b)$的点对画一条斜率为$q$的直线,最大化截距。
就像平移一样,如下图所示,黑点代表一个$(a,b)$,橙点代表其所对应的截距,也就是$(a*q+b)$:

我们要最大化截距,而直线都是平行地平移来平移去,直线斜率的正负已经不重要了,取上凸壳的点才有可能是最优解:

注意并不是取上凸壳最高的点就是最优解,拿上图的最右上角的黑点举例,在另一个例子中,反倒是经过另一个点的直线截距最大:

但是不管怎样,如果从左到右看上凸壳的点,截距的变化是一个单峰函数。
那么我们就可以在上凸壳进行三分(以每一个点的截距为关键值)。
点集的变化?
建立一棵以时间为下标的线段树,每一个线段树节点都有一个上凸壳,包含在这个节点代表的时间段内,出现的所有点对。
每一个点对$(a,b)$有一个存在区间$[l,r]$,对于线段树上$[l,r]$覆盖的线段树节点,往它们里面都加入该点对。
对于查询操作,若在时间$i$询问$q$,就从根节点遍历到下标为$[i,i]$的叶子节点。在路上的每一个节点,都在它的上凸壳内进行一次三分(代入$q$),最后取所有经过的点的最大值即可。
为什么?因为在访问$[i,i]$的时候经过了一个节点$u$,那么$u$一定包含$[i,i]$。所以对所有经过节点三分,一定考虑到了询问$i$时还活着的所有点对。
维护上凸壳时,由于单调栈的模拟需要$a$递增,如果每一个节点插完之后自己再排序就太慢了。可以先离线记录所有的点对,按$a$递增排序,逐个插入线段树,这样就省去了每个节点内部的排序,因为插入的点的$a$一定不会小于整个线段树先前存在的任意一个$a$。
感觉是道神题orz
#include <cstdio>
#include <cstring>
using namespace std;
const int N=,INF=;
int n,h[N],tot,d[N],root,all,sum[N];
int f[N][][N/];
struct Edge{int v,next;}g[N*];
inline int min(int x,int y){return x<y?x:y;}
inline void upd(int &x,int y){if(y<x) x=y;}
inline void addEdge(int u,int v){g[++tot].v=v; g[tot].next=h[u]; h[u]=tot;}
inline int rd(){
char c=getchar(); int x=;
while(c<''||c>'') c=getchar(); x=c-'';
while(''<=(c=getchar())&&c<='') x=x*+c-'';
return x;
}
void init(){
for(int u=;u<=n;u++)
if(d[u]==) all++;
else if(!root) root=u;
for(int i=;i<=n;i++)
for(int j=;j<=;j++)
for(int k=,up=all/;k<=up;k++) f[i][j][k]=INF;
}
void dfs(int u,int fa){
if(d[u]==){
f[u][][]=f[u][][]=;
sum[u]=;
return;
}
for(int i=h[u],v;i;i=g[i].next)
if((v=g[i].v)!=fa){
dfs(v,u);
sum[u]+=sum[v];
}
int fson=;
for(int i=h[u],v;i;i=g[i].next)
if((v=g[i].v)!=fa){
if(!fson){
for(int j=,up=min(min(sum[u],sum[v]),all/);j<=up;j++){
f[u][][j]=min(f[v][][j],f[v][][j]+);
f[u][][j]=min(f[v][][j]+,f[v][][j]);
}
fson=;
continue;
}
int F0,F1;
for(int j=min(sum[u],all/);j>=;j--){
f[u][][j]+=min(f[v][][],f[v][][]+);
f[u][][j]+=min(f[v][][]+,f[v][][]);
for(int k=,upk=min(sum[v],j);k<=upk;k++){
upd(f[u][][j],f[u][][j-k]+min(f[v][][k],f[v][][k]+));
upd(f[u][][j],f[u][][j-k]+min(f[v][][k]+,f[v][][k]));
}
}
}
}
int main(){
n=rd();
for(int u,v,i=;i<n;i++){
u=rd(); v=rd();
addEdge(u,v); addEdge(v,u);
d[u]++; d[v]++;
}
if(n==){puts(""); return ;}
init();
if(all&) return ;
dfs(root,);
printf("%d\n",min(f[root][][all/],f[root][][all/]));
return ;
}
奇妙代码
【CF 678F】Lena and Queries的更多相关文章
- 【CF 710F】String Set Queries
在校内OJ上A了,没有加强制在线的东西..不放链接了. 这道题题意是维护一个字符串集合,支持三种操作: 1.加字符串 2.删字符串 3.查询集合中的所有字符串在给出的模板串中出现的次数 操作数\(m ...
- 【CF#338D】GCD Table
[题目描述] 有一张N,M<=10^12的表格,i行j列的元素是gcd(i,j) 读入一个长度不超过10^4,元素不超过10^12的序列a[1..k],问是否在某一行中出现过 [题解] 要保证g ...
- 【CF#303D】Rotatable Number
[题目描述] Bike是一位机智的少年,非常喜欢数学.他受到142857的启发,发明了一种叫做“循环数”的数. 如你所见,142857是一个神奇的数字,因为它的所有循环排列能由它乘以1,2,...,6 ...
- 【35.20%】【CF 706D】Vasiliy's Multiset
time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standa ...
- 【CF 463F】Escape Through Leaf
题意 给你一棵 \(n\) 个点的树,每个节点有两个权值 \(a_i,b_i\). 从一个点 \(u\) 可以跳到以其为根的子树内的任意一点 \(v\)(不能跳到 \(u\) 自己),代价是 \(a_ ...
- 【CF 453A】 A. Little Pony and Expected Maximum(期望、快速幂)
A. Little Pony and Expected Maximum time limit per test 1 second memory limit per test 256 megabytes ...
- 【CF 585E】 E. Present for Vitalik the Philatelist
E. Present for Vitalik the Philatelist time limit per test 5 seconds memory limit per test 256 megab ...
- 【26.8%】【CF 46D】Parking Lot
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- 【31.42%】【CF 714A】Meeting of Old Friends
time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...
随机推荐
- robotframework安装及入门指南
将很久之前自己在本地记录的一些笔记发表到随笔来,希望能够帮到一些童鞋~ robotframework安装及入门指南 本文主要介绍robotframework在windows环境的安装过程! 安装步骤 ...
- 如何为form表单的button设置submit事件
若button按钮没有type属性,浏览器默认按照type=submit逻辑处理,这样若将没有type的button放在form表单中,点击按钮就会执行form表单提交
- 跳转语句Break、continue
跳转语句Break.continue 1.break -跳出 作用范围:switch或循环语句; -当break语句单独存在时,下面不需要定义其他语句,因为直接被跳出,不执行下面的语句. -break ...
- linux 文件名称前后缀操作函数----取目录函数dir、取文件名称函数notdir、取后缀函数suffix、取前缀basename、加后缀函数addsuffix、加前缀addprefix、连接函数join
1.1 文件名操作函数 下面我们要介绍的函数主要是处理文件名的.每个函数的参数字符串都会被当做一个或是一系列的文件名来对待. 1.1.1 取目录函数dir $(dir < ...
- R语言-图形初阶
在本节中,主要目的是如何使用R语言做出简单的图形 案例1:做出wt和mpg之间的关系 attach(mtcars) plot(wt,mpg) abline(lm(mpg~wt)) title('Reg ...
- flex基本概念
基本使用 任何一个容器都可以指定为flex布局 .box { display: flex; } 行内元素也可以使用flex .box { display: inline-flex; } Webkit内 ...
- git修改目录名称
同步代码 $ git pull origin master 修改某个目录名称 $ git mv doc docs 把doc目录修改为docs 提交至远程仓库 $ git push origin mas ...
- 一次saltstack环境变量的坑
现场环境: salt-minion端: ip:10.0.3.149 环境:使用 nvm装的nodejs 受用nodejs自带的npm 安装pm2 sal-master端: IP:10.0 ...
- python监控接口请求
#!/usr/bin/env python #coding=utf8 import time,os,sched,urllib,httplib import smtplib import string ...
- RMI基础篇
远程方法调用(Remote Method Invocation,RMI)从JDK1.1就已经实现,它大大增强了Java开发分布式应用的能力. RMI可以实现通过网络完成不同JVM间的通信,不仅可以传递 ...