首页 > 其他分享 >luogu4198题解

luogu4198题解

时间:2024-09-09 14:49:08浏览次数:4  
标签:return 数列 int 题解 mk ans id luogu4198

随机说话

这个题做法没见过记一下。
我一开始以为是李超树的题,结果把李超树打上之后就不会做了。
然后题读错了写了一个弱化版。

题目分析

做法参考
这个题题意只是假装是一个有关线段的题。
简化之后的题意如下。

有一个初始都为 \(0\) 的实数数列,每一次会修改位置 \(x\) 的数为 \(k\)(其中 \(k=\frac{y}{x}\))。求每次修改之后从第一个位置开始以下列规则选择的数列的长度。

如果在 \(x\) 位置之前选择的数列中没有大于 \(k_x\) 的数,就选择 \(k_x\)。

这个题需要一个数据结构来维护。
数据结构的选取需要题目性质的分析。
经下面分析可以得到需要的数据结构是线段树。

题目很重要的性质是这个选取数列的方法。
很容易发现我们选出的这个数列是单调的,而且一定会选 \(k_1\) 和最大的 \(k\)。
我们考虑区间选取的数列进行合并的过程。
对于两个有左右顺序的数列,发现左边的数列里的数是一定会被选的。
而右边的数列中小于左边数列的 \(k\) 的最大值的数 \(k_{max}\) 都不会被选,反之如果右边选取的第一个数就大于 \(k_{max}\) 就会全选右边的。
除了这两种情况的一般情况,我们就需要找到右边被选取的第一个 \(k_x\),由于单调性的原因是 \(k_x\) 左边都不会被选,\(k_x\) 的右边都会被选。
于是我们可以考虑这个区间分出来的两个子区间,下列的左右区间都指这两个子区间。
如果左区间的最大值小于等于 \(k_{max}\) 就都不会选,与右区间进行合并即可。
而左区间的最大值大于 \(k_{max}\) 的时候,右侧选出的一定会被选,左区间合并之后直接累加右区间选的即可。
到此为止,我们就找到了一个复杂度为 \(O(\log n)\) 的 pushup 的方法。
用线段树来维护数据,单点修改需要 pushup \(\log n\) 次,查询的时间复杂度仅为 \(O(1)\),总的时间复杂度为 \(O(\log ^2n)\),可以通过此题。

代码如下。

//照https://www.luogu.com.cn/article/0xufwccu打的 
#include<bits/stdc++.h>
using namespace std;
constexpr int MAXN=1e5+10;
constexpr double eps=1e-12;
int n,m;
double k[MAXN];
struct SegmentTreeNode{
	double maxk;
	int ans;
	#define k(id) segt[(id)].maxk
	#define ans(id) segt[(id)].ans
}segt[MAXN<<2];
int cmp(double x,double y){
	if(x-y>eps)return 1;
	else if(y-x>eps)return -1;
	else return 0;
}
#define lid (id<<1)
#define rid ((id<<1)|1)
#define mid ((l+r)>>1)
void pushup(int id){
	k(id)=max(k(lid),k(rid));
}
int query(int id,int l,int r,double mk){
	if(cmp(k[l],mk)==1)return ans(id);
	if(cmp(k(id),mk)==-1)return 0;
	if(l==r)return cmp(k(id),mk)==1;
	if(cmp(k(lid),mk)==1)return query(lid,l,mid,mk)+ans(id)-ans(lid);
	else return query(rid,mid+1,r,mk);
}
void change(int id,int l,int r,int loc){
	if(l==r){
		k(id)=k[l];
		ans(id)=1;
		return;
	}
	if(loc<=mid)change(lid,l,mid,loc);
	else change(rid,mid+1,r,loc);
	pushup(id);
	ans(id)=ans(lid)+query(rid,mid+1,r,k(lid));
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,x,y;i<=m;++i){
		scanf("%d%d",&x,&y);
		k[x]=1.0*y/x;
		change(1,1,n,x);
		printf("%d\n",ans(1));
	}
	return 0;
}

标签:return,数列,int,题解,mk,ans,id,luogu4198
From: https://www.cnblogs.com/LiJoQiao/p/18404534

相关文章

  • Flutter 3.24 构建 release 抛出部分依赖 AAPT: error: resource android:attr/lStar
    问题截图:一些讨论:https://github.com/transistorsoft/flutter_background_fetch/issues/369问题原因及解决方案:@Aziz-T该问题与插件的compileSdkVersion和targetSdkVersion有关。出现该问题的原因是部分插件的compileSdkVersion和targetSdkVersion版本过旧。请前往......
  • P2471 [SCOI2007] 降雨量 题解
    题目传送门分析分讨题。首先发现是RMQ问题(区间最值),可以用线段树或ST表来维护(代码为线段树,因为我忘记ST表怎么写了)。然后发现有些年份不明确导致区间判断似乎不好搞。但事实上只要判断下标差是否等于年份差即可得出该区间有无不明确年份。其次考虑“必真”,“必假”,“......
  • 【洛谷 P1996】约瑟夫问题 题解(数组+模拟+循环)
    约瑟夫问题题目描述个人围成一圈,从第一个人开始报数,数到的人出列,再由下一个人重新从开始报数,数到的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰名小朋友,而该题是全部出圈。输入......
  • 题解 GZOI2023D2B【乒乓球】
    4s,512M题目描述Alice和Bob在打乒乓球,乒乓球比赛的规则是这样的:一场比赛中两位选手将进行若干局比赛,选手只需要赢得\(X\)局比赛就宣告其胜利;每局比赛中两位选手将进行若干盘比赛,选手只需要赢得\(Y\)盘比赛就宣告其胜利;每盘比赛中两位选手将进行乒乓球对决,有且仅有一位选......
  • AtCoder Beginner Contest 274 A~E 题解
    吐槽:这比赛名字为啥没有英文版。。。A-BattingAverage题目大意给定整数\(A,B\),输出\(\fracBA\),保留三位小数。\(1\leA\le10\)\(0\leB\leA\)分析签到题,使用printf或cout格式化输出即可。代码#include<cstdio>usingnamespacestd;intmain(){ inta,b; sc......
  • TOYOTA MOTOR CORPORATION Programming Contest 2023#1 (AtCoder Beginner Contest 29
    好久没写题解了,这就来水一篇。A-JobInterview题目大意给定一个长为\(N\)的字符串\(S\),由o、-、x组成。判断\(S\)是否符合下列条件:\(S\)中至少有一个o。\(S\)中没有x。\(1\leN\le100\)分析签到题。直接按题意模拟即可。代码#include<cstdio>usingn......
  • AtCoder Beginner Contest 318 G - Typical Path Problem 题解
    G-TypicalPathProblem题目大意给定一张\(N\)个点、\(M\)条边的简单无向图\(G\)和三个整数\(A,B,C\)。是否存在一条从顶点\(A\)到\(C\),且经过\(B\)的简单路径?数据范围:\(3\leN\le2\times10^5\)\(N-1\leM\le\min(\frac{N(N-1)}2,2\times10^5)\)\(1\leA......
  • UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)
    A-ChristmasPresent题目大意给定两个正整数\(B,G\)(\(1\leB,G\le1000\)且\(B\neG\)),判断哪个更大。分析模拟即可。代码#include<cstdio>usingnamespacestd;intmain(){ intb,g; scanf("%d%d",&b,&g); puts(b>g?"Bat":&qu......
  • 洛谷 P9754 [CSP-S 2023] 结构体 题解
    题目传送门洛谷博客CSDNCSP-S2023T3结构体题解基本思路本题主要考查编码能力,所以直接给出基本思路:由于可以递归式的创建元素,最多可以同时存在\(100^{100}\)个不同的基础类型的元素。即使算上最大地址的限制,元素的数量也能达到\(10^{18}\)。显然,依次构造每个元素,在空......
  • AT_agc027_f [AGC027F] Grafting 题解
    笑点解析:NOIP模拟赛把这题放在T3。因为每一个点只能动一次,答案一定\(\len\),所以我们分两种情况讨论:当答案小于\(n\)答案如果小于\(n\),那么一定有一个点是一直没有被动过的。我们枚举这个点,将无根树转化为两棵以这个点为根的有根树。我们将第一棵树和第二棵树同构的部分......