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

  1. 【CF 710F】String Set Queries

    在校内OJ上A了,没有加强制在线的东西..不放链接了. 这道题题意是维护一个字符串集合,支持三种操作: 1.加字符串 2.删字符串 3.查询集合中的所有字符串在给出的模板串中出现的次数 操作数\(m ...

  2. 【CF#338D】GCD Table

    [题目描述] 有一张N,M<=10^12的表格,i行j列的元素是gcd(i,j) 读入一个长度不超过10^4,元素不超过10^12的序列a[1..k],问是否在某一行中出现过 [题解] 要保证g ...

  3. 【CF#303D】Rotatable Number

    [题目描述] Bike是一位机智的少年,非常喜欢数学.他受到142857的启发,发明了一种叫做“循环数”的数. 如你所见,142857是一个神奇的数字,因为它的所有循环排列能由它乘以1,2,...,6 ...

  4. 【35.20%】【CF 706D】Vasiliy's Multiset

    time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standa ...

  5. 【CF 463F】Escape Through Leaf

    题意 给你一棵 \(n\) 个点的树,每个节点有两个权值 \(a_i,b_i\). 从一个点 \(u\) 可以跳到以其为根的子树内的任意一点 \(v\)(不能跳到 \(u\) 自己),代价是 \(a_ ...

  6. 【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 ...

  7. 【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 ...

  8. 【26.8%】【CF 46D】Parking Lot

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

  9. 【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 ...

随机推荐

  1. eclipse-java开发实用快捷键

    Expand All:ctrl+小键盘* Collapse All:ctrl+shift+小键盘/

  2. 解决Flink输出日志中时间比当前时间晚8个小时的问题

    Flink安装在CentOS7上,默认时间是UTC时间,查看Flink日志,发现输出时间比当前时间晚8个小时. 通过如下命令,调整成北京时间 cp /usr/share/zoneinfo/Asia/S ...

  3. redhat linux/CentOS 6/7 如何关闭防火墙?

    redhat linux/CentOS 6/7 如何关闭防火墙?关闭防火墙iptables的具体命令如下: 临时性的完全关闭防火墙,可以不重启机器(但是重启服务器后iptables防火墙服务会自动随系 ...

  4. 【视频编解码·学习笔记】4. H.264的码流封装格式

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

  5. 企业级Docker私有仓库部署(https)

    部署环境 Centos7.3 x64 docker-ce-17.06.0 docker-compose-1.15.0 Python-2.7.5(系统默认) 部署目标 使用HTTPS协议 支持Clair ...

  6. 2018Pycharm激活方法

    1.将"0.0.0.0 account.jetbrains.com"添加到hosts文件中 2.打开http://idea.lanyus.com/ 3.获取激活码,粘贴到第二个选项 ...

  7. 关于css选择器的一些细节

    1.如何区分一个html标签的不同样式 使用标签名.类名的方式解决 如果希望特别强调其中的某一个或几个元素,处理的方案有三个: 1.id选择器 2.class选择器 3.层级选择器 看下面的代码: & ...

  8. xBIM 多个IFC文件合并

    目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...

  9. selenium打开chrome浏览器代码

    import os from selenium import webdriver chromedriver = "C:\Program Files (x86)\Google\Chrome\A ...

  10. 洛谷 P3616 富金森林公园 [树状数组]

    传送门 维护一个山脉,单点修改,查询有多少山峰高出水面 我是沙茶沙茶题都不会做只想到无修改可以用扫描线 答案就是所有比水面高的-相邻都比水面高的啊 因为没有区间询问写个$BIT$都可以 有区间询问?可 ...