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. CentOS7 配置花生壳开机启动

    在家安装服务器,外地可以随时登陆,感觉花生壳特别方便,具体路由器配置请参考http://service.oray.com/question/2486.html. 我使用的操作系统是 [root@loc ...

  2. WebSphere--定制配置

    本节介绍如何启动和使用 WebSphere应用服务器的管理器(一个图形界面)为 Servlet 活动和 WebSphere应用服务器的组件定制基本设置参数.    1.启动 WebSphere应用服务 ...

  3. keepalived深度结合lvs_dr模式

    keepalived与dr模式结合 keepalived介绍 keepalived可提供vrrp以及health-check功能,可以只用它提供双机浮动的vip(vrrp虚拟路由功能), 这样可以简单 ...

  4. shell第四篇(上)

    第四篇了解Shell 命令执行流程图 {网中人大哥推荐参考Learning the Bash Shell, 2nd Edition,第 178页:中文版229页} Shell 从标准输入或脚本中读取的 ...

  5. 4个强大的Linux服务器监控工具[转]

    本文介绍了一些可以用来监控网络使用情况的Linux命令行工具.这些工具可以监控通过网络接口传输的数据,并测量目前哪些数据所传输的速度.入站流量和出站流量分开来显示. 一些命令可以显示单个进程所使用的带 ...

  6. DOM中对象的获得

    DOM的所有对象会在页面打开时,由浏览器页面创建. 浏览器把dom定点对象Document对像的引用交给了window对象. 1.document对象的获得    var doc = window.d ...

  7. 蓝桥杯练习系统—基础练习 2n皇后问题

    问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和n个白皇后, 使任意的两个黑皇后都不在同一行.同一列或同一条对角线上,任意的两个白皇后都不在同一行. 同一列或 ...

  8. VS下WPF自定义控件的基本步骤和基本代码实现

    一.自定义控件的基本步骤: (本示例项目名称为:W:添加的自定义控件名称为) 1.  在"解决方案资源管理器"窗口的项目名上: 右击à添加à新建项(Ctrl+Shift+A) 2. ...

  9. Go笔记-继承

    [Go中继承的实现]     当一个匿名类型被内嵌在结构体中时,匿名类型的可见方法也同样被内嵌,这在效果上等同于外层类型 继承 了这些方法:将父类型放在子类型中来实现亚型 package main i ...

  10. BZOJ 3744: Gty的妹子序列 [分块]

    传送门 题意:询问区间内逆序对数 感觉这种题都成套路题了 两个预处理$f[i][j]$块i到j的逆序对数,$s[i][j]$前i块$\le j$的有多少个 f我直接处理成到元素j,方便一点 用个树状数 ...