【2020.11.19提高组模拟】二次剩余two 题解
【2020.11.19提高组模拟】二次剩余two 题解
题目描述
有\(n\)个二次函数,每个二次函数可以用两个值\(m,k\)描述:
\]
现在有\(q\)次操作:
1.插入一个二次函数\((m,k)\)
2.\((x,t)\)删除所有\(f(x)\le t\)的二次函数。
输出每次操作后还剩下的二次函数个数。
对于所有的数据,保证\(n,q,m,k,x,t\in [1,1e5]\)
以下是数据范围表格节选。
| \(n,q\le\) | \(m\le\) | |
|---|---|---|
| 1~4 | 20000 | 100000 | 
| 5~6 | 100000 | 1000 | 
| 7~10 | 100000 | 100000 | 
Solution
考场上我先想到了对\(n^2\)的暴力进行卡常优化——结果就过了qaq老师不要重测卡我啊!
虽然这不是正解,但是我还是记录一下吧。
用了两个栈,先把开始的二次函数存到栈1。
对于操作1,直接入栈1。
对于操作2,扫描栈1内所有的二次函数,若无需删去就加入栈2,否则不加;再将栈2复制到栈1。
可以利用类似滚动数组的方法在两个栈之间回滚,省去复制操作;不要暴力清空栈,只要把size赋值为0就好。这样每次进行操作2需要遍历的次数仅仅为当前二次函数的个数。
Code-\(O(n^2)\)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define debug printf("Now is %d\n",__LINE__);
using namespace std;
template<class T>inline void read(T&x)
{
    char ch=getchar();
    int fu;
    while(!isdigit(ch)&&ch!='-') ch=getchar();
    if(ch=='-') fu=-1,ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    x*=fu;
}
inline int read()
{
	int x=0,fu=1;
    char ch=getchar();
    while(!isdigit(ch)&&ch!='-') ch=getchar();
    if(ch=='-') fu=-1,ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
    int g=0;
    if(x<0) x=-x,putchar('-');
    do{G[++g]=x%10;x/=10;}while(x);
    for(re int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n,q;
struct two
{
	LL m,k;
}sk[2][1000010];
int size[2];
int main()
{
	freopen("two.in","r",stdin);
	freopen("two.out","w",stdout);
	n=read();
	q=read();
	for(re int i=1;i<=n;i++) sk[0][i].m=read(),sk[0][i].k=read();
	size[0]=n;
	int op,x,t;
	bool flag=0;
	while(q--)
	{
		op=read();
		if(op==1)
		{
			sk[flag][++size[flag]].m=read();
			sk[flag][size[flag]].k=read();
			write(size[flag]);
		}
		else
		{
			x=read();
			t=read();
			for(re int i=1;i<=size[flag];i++)
			{
				if((x-sk[flag][i].m)*(x-sk[flag][i].m)+sk[flag][i].k>t) sk[!flag][++size[!flag]]=sk[flag][i];
			}
			size[flag]=0;
			flag=!flag;
			write(size[flag]);
		}
	}
	return 0;
}
记得开\(\texttt{long long}\)。
Std
因为\(k\in \mathbb N^+\),所以先不考虑k。
\Rightarrow -\sqrt t \le x-m\le \sqrt t\\
\Rightarrow x-\sqrt t\le m\le x+\sqrt t
\]
所以,可能会被删去的二次函数的\(m\)只可能在\(x\pm\sqrt t\)中。
而对于相同的\(m\),k小的应该越会被删去。
所以我们对每种m都用一个小根堆,扫描时只要扫\(x-\sqrt t\le m\le x+\sqrt t\)区间中的堆,然后尽量取出合法的二次函数即可。
时间复杂度:\(O((n+q)\log n+q\sqrt t)\)。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define debug printf("Now is %d\n",__LINE__);
using namespace std;
template<class T>inline void read(T&x)
{
    char ch=getchar();
    int fu;
    while(!isdigit(ch)&&ch!='-') ch=getchar();
    if(ch=='-') fu=-1,ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    x*=fu;
}
inline int read()
{
	int x=0,fu=1;
    char ch=getchar();
    while(!isdigit(ch)&&ch!='-') ch=getchar();
    if(ch=='-') fu=-1,ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
    int g=0;
    if(x<0) x=-x,putchar('-');
    do{G[++g]=x%10;x/=10;}while(x);
    for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
LL n,q,ans;
priority_queue<int>a[100010];
int main()
{
//	freopen("two.in","r",stdin);
//	freopen("two.out","w",stdout);
	n=read();
	q=read();
	for(re int i=1,m,k;i<=n;i++) m=read(),k=read(),a[m].push(-k);
	ans=n;
	int op,x,y,l,r;
	while(q--)
	{
		op=read();
		if(op==1)
		{
			x=read();
			y=read();
			a[x].push(-y);
			ans++;
		}
		else
		{
			x=read();
			y=read();
			l=x-sqrt(y);
			r=x+sqrt(y);
			for(re int i=max(l,1);i<=r&&i<=100000;i++)
			{
				while(!a[i].empty())
				{
					if((x-i)*(LL)(x-i)-a[i].top()>y) break;
					a[i].pop();
					ans--;
				}
			}
		}
		write(ans);
	}
	return 0;
}
Attention
不要抱有侥幸心理。这次能过,下次还是会\(40pts\)乃至\(20pts\)的。
【2020.11.19提高组模拟】二次剩余two 题解的更多相关文章
- 【2020.11.28提高组模拟】T1染色(color)
		
[2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...
 - 【2020.11.28提高组模拟】T2 序列(array)
		
序列(array) 题目描述 给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...
 - 【2020.11.30提高组模拟】剪辣椒(chilli)
		
剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...
 - 【2020.11.30提高组模拟】删边(delete)
		
删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...
 - JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)
		
题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...
 - JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)
		
题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...
 - 11.5NOIP2018提高组模拟题
		
书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...
 - 【2020.12.03提高组模拟】A组反思
		
估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...
 - 【2020.12.01提高组模拟】卡特兰数(catalan)
		
题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...
 - 【2020.12.01提高组模拟】A组反思
		
105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...
 
随机推荐
- git 合并分支 merge
			
git 分支开发 git 分支开发,分支(feature)同步主干(master)代码,以及最终分支合并到主干的操作流程 由于 rebase 执行速度慢,分支同步主干代码时,分支的每次提交都可能和 ...
 - mysql导入失败
			
mysqldump导出数据库表的数据会加上一些SQL的注释,这些注释会在批量执行SQL语句中造成错误,需要提前删除. sql开始部分: SET @@SESSION.SQL_LOG_BIN = @MYS ...
 - 团队小规模本地大模型服务平台搭建 - Ubuntu
			
实现目标和考虑因素 部署一个支持多用户同时使用.多模型运行的离线局域网大模型服务器 需要考虑以下几个关键因素: 大模型的加载和管理.使用一个基础大模型,根据实战需要创建多个专用模型,模型管理方便可靠. ...
 - 面试题-Java多线程基础、实现工具和可见性保证(新更新版)
			
前言 Java多线程部分的题目,是我根据Java Guide的面试突击版本V3.0再整理出来的,其中,我选择了一些比较重要的问题,并重新做出相应回答,并添加了一些比较重要的问题,希望对大家起到一定的帮 ...
 - Java 与 LLM 大模型融合的技术革命:JBoltAI 如何重构企业级 AI 开发范式
			
Java 与 LLM 大模型融合的技术革命:JBoltAI 如何重构企业级 AI 开发范式 一.Java 技术栈的智能化转型挑战 随着 LLM(大语言模型)技术的突破,全球超过 900 万家 Java ...
 - 💻开源项目介绍-NewsNow-优雅的实时新闻聚合平台
			
news.zktww.vip 引言 在信息洪流中,如何优雅地获取新闻? 在当今信息爆炸的时代,我们每天需要在微博.知乎.Twitter.GitHub等平台间频繁切换,才能捕捉到最新的热点动态. New ...
 - 结合钉钉机器人用python写监控打印机碳粉状态程序
			
点击查看代码 from pysnmp.hlapi import * import requests import json # 配置信息 PRINTER_IP = '1.1.1.1' # 打印机IP ...
 - 做个小实验,帮你理解 Git 工作区与暂存区
			
做个小实验,帮你理解 Git 工作区与暂存区 Git 很重要,本文将通过实验的方式,带你理解 Git 的工作区.暂存区以及相关命令的使用. 1. 什么是工作区和暂存区? 在 Git 中,工作区和暂存区 ...
 - 墨刀上线高级交互功能,能否超越Axure?
			
引言 近期,国内主流原型设计工具墨刀推出了"变量.条件判断.函数"等功能,立刻在交互设计师与资深产品经理群体中引起热议.作为国产轻量级原型设计工具的龙头代表,墨刀早已俘获了中小团队 ...
 - 作业时间之"最早时间和最晚时间"
			
一.从左往右(小到大)算最早时间 0+2=2 0+3=3 因为3比2大所以选择3(早大晚小),需活动无时间所以不用加 3+4=7 7+3=10 因为13号点有两个 2+5=7 和 11号点的10(虚活 ...