ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF809D-Hitchhiking in the Baltic States【FhqTreap】

2022-02-06 16:04:12  阅读:114  来源: 互联网

标签:10 return int Hitchhiking States leq Baltic include CF809D


正题

题目链接:https://www.luogu.com.cn/problem/CF809D


正题

题目链接:https://www.luogu.com.cn/problem/CF809D


题目大意

有一个长度为\(n\)的序列\(a\),要求\(a_i\in[l_i,r_i]\),要求使得\(a\)的最长严格上升子序列最长。

\(1\leq n\leq 3\times 10^5,1\leq l_i\leq r_i\leq 10^9\)


解题思路

考虑一下暴力的做法,我们设\(f_i\)表示在目前的序列中后面加个数字\(i\)为结尾时的最长上升子序列,那么显然\(f\)是单调不降的。

同理由于是严格上升,所以我们\(f\)不可能一次升\(2\)的值,也就是\(f_i\leq f_{i-1}+1\)。所以我们可以考虑维护\(f_i=f_{i-1}+1\)的位置,也就是维护\(f\)的差分数组中的\(1\)的位置。

考虑新加入一个\([l,r]\)时的变化,那对于所有\(i\in[l+1,r+1]\)都有\(f_i=max\{f_i,f_j+1\}(j<i)\),注意到\(1\)位置的变化我们可以得出一下结论,当修改\([l,r]\)时需要

  1. 将\([l+1,r]\)中所有\(1\)的后面那个\(1\)移动到这个\(1\)的后一位。
  2. 将\([l+1,r]\)中的第一个\(1\)移动到\(l+1\)处

这个操作看起来很难实现,实际上我们可以将第一个视为将\([l+1,r+1]\)中的\(1\)往后移一格。

我们用FhqTreap维护\(1\)的位置,然后把\((r,\infty)\)中第一个\(1\)删除,\([l+1,r]\)中的所有\(1\)往后移一格,再在\(l+1\)这个位置插一个\(1\)就好了。

时间复杂度:\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+10;
int n,cnt,rt,w[N],dat[N],lazy[N],siz[N],t[N][2];
void Downdata(int x){
	if(!lazy[x])return;
	for(int i=0;i<2;i++){
		if(!t[x][i])continue;
		lazy[t[x][i]]+=lazy[x];
		w[t[x][i]]+=lazy[x];
	}
	lazy[x]=0;return;
}
int NewNode(int val){
	siz[++cnt]=1;dat[cnt]=rand();
	w[cnt]=val;return cnt;
}
void PushUp(int x){
	siz[x]=siz[t[x][0]]+siz[t[x][1]]+1;
	return;
}
void Split(int &x,int &y,int p,int k){
	if(!p){x=y=0;return;}Downdata(p);
	if(w[p]<=k)x=p,Split(t[x][1],y,t[p][1],k);
	else y=p,Split(x,t[y][0],t[p][0],k);
	PushUp(p);return;
}
int Merge(int x,int y){
	Downdata(x);Downdata(y);
	if(!x||!y)return x|y;
	if(dat[x]<dat[y]){
		t[x][1]=Merge(t[x][1],y);
		PushUp(x);return x;
	}
	else{
		t[y][0]=Merge(x,t[y][0]);
		PushUp(y);return y;
	}
	return x|y;
}
int Findk(int x,int k){
	if(siz[t[x][0]]>=k)return Findk(t[x][0],k);
	if(siz[t[x][0]]+1==k)return x;
	return Findk(t[x][1],k-siz[t[x][0]]-1);
}
int main()
{
//	freopen("vague.in","r",stdin);
//	freopen("vague.out","w",stdout);
	srand(19260817);
	scanf("%d",&n);
	for(int i=1,l,r;i<=n;i++){
		scanf("%d%d",&l,&r);
		int x,y,z;l++;
		Split(x,y,rt,l-1);
		Split(y,z,y,r);
		if(z){
			int v=w[Findk(z,1)],nu;
			Split(nu,z,z,v);
		}
		if(y)lazy[y]++,w[y]++;
		y=Merge(NewNode(l),y);
		y=Merge(y,z);
		rt=Merge(x,y);
	}
	printf("%d\n",siz[rt]);
	return 0;
}

标签:10,return,int,Hitchhiking,States,leq,Baltic,include,CF809D
来源: https://www.cnblogs.com/QuantAsk/p/15865747.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有