首页 > 其他分享 >CF809D.Hitchhiking in the Baltic States

CF809D.Hitchhiking in the Baltic States

时间:2022-12-07 21:01:54浏览次数:34  
标签:ch int Hitchhiking pos States fa tag Baltic dp

题意

给出 \(n\) 个区间 \([l_i,r_i]\) 和 \(n\) 个未知数 \(a_1,a_2,\dots,a_n\),现在你要确定这 \(n\) 个数,使得 \(a_i\in[l_i,r_i]\),并且这个序列的最长严格上升子序列尽可能大,求这个最大值。

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

题解

首先考虑 \(n^2\) dp, 设 \(dp[i]\) 表示长度为\(i\)的最长上升子序列的末尾最少是多少。

那么转移方程如下。

  • \(dp[i - 1] < l, dp[i] = \min(dp[i], l)\)
  • $l <= dp[i - 1]< r, dp[i] = dp[i - 1] + 1) $
  • \(dp[i - 1] >= r, dp[i] = dp[i]\)

观察知 \(dp_i\) 具有单调性。

对于第三部分我们显然可以不管它。

对于第二部分, 相当于区间平移, 并且区间加 \(+1\).

对于第一部分,就是把第一个大于等于 \(l\) 的值变为 \(l\)

对于区间平移, 相当于在区间前加入一个元素, 并删除区间后的第一个元素。

综上, \(dp\) 转移相当于删除第一个大于等于 \(r\) 的元素,把 \(l \leq dp[i] < r\) 的 \(dp[i]\) 加 \(1\) , 然后在第一个大于等于 \(l\) 的位置前插入一个 \(l\) 。

因为涉及区间操作和插入删除, 考虑 \(splay\) 维护。

时间复杂度: \(\Theta(nlogn)\)

  1. 要注意哨兵节点大小, 不能就设1e9, 我调了几个小时。

代码

点击查看代码
#include <stdio.h>
#include <string.h>
#include <iostream>
const int N = 6e5, INF = 1e9;
using namespace std;

int n, dp[N + 5], l[N + 5], r[N + 5], Opt;
int cnt, ans;

void read(int &x) {
	x = 0; int w = 1; char c = getchar(); for(; c < '0' || c >  '9'; c = getchar()) if (c == '-') w =  -1;
	for(; c <= '9' && c >= '0'; c = getchar()) x = x * 10 + c - '0'; x *= w;
}

struct spla{
	int ch[N + 5][2], fa[N + 5], val[N + 5], tag[N + 5],rt, tot;
	void pushdown(int p) {
		if (tag[p]) {
			if (ch[p][0]) {val[ch[p][0]] += tag[p]; tag[ch[p][0]] += tag[p];}
			if (ch[p][1]) {val[ch[p][1]] += tag[p]; tag[ch[p][1]] += tag[p];}
			tag[p] = 0;
		}
	}
	int get(int x) {return x == ch[fa[x]][1];}
	void rotate(int x) {
		int y = fa[x], z = fa[y], k = get(x);
		ch[z][get(y)] = x; fa[x] = z;
		ch[y][k] = ch[x][k^1]; fa[ch[y][k]] = y;
		ch[x][k^1] = y; fa[y] = x;
	}
	void splay(int x, int k) {
		while(fa[x] != k) {
			int y = fa[x], z = fa[y];
			pushdown(z); pushdown(y); pushdown(x);
			if (z != k) {
				if (get(x) != get(y)) rotate(x);
				else rotate(y);
			}
			rotate(x);
		}
		if (!k) rt = x;
	}
	void insert(int &pos, int v, int f) {
		if (!pos) {
			pos = ++tot; fa[pos] = f; val[pos] = v;
			splay(pos, 0);
			return;
		}
		pushdown(pos);
		if (v < val[pos]) insert(ch[pos][0], v, pos);
		else insert(ch[pos][1], v, pos);
	}
	int find(int x) { //  找最后一个小于x
		int p = rt, ans = 0;
		while(p) {
			pushdown(p);
			if (val[p] < x) {
				ans = p; p = ch[p][1];
			}
			else p = ch[p][0];
		}
		return ans;
	}
	int Nxt(int x) {
		splay(x, 0); x = ch[x][1];
		while(ch[x][0]) x = ch[x][0];
		return x;
	}
	int Pre(int x) {
		splay(x, 0); x = ch[x][0];
		while(ch[x][1]) x = ch[x][1];
		return x;
	}
	void del(int x) {
		int u = Pre(x), v = Nxt(x);
		splay(u, 0); splay(v, u);
		fa[x] = 0;ch[v][0] = 0;
	}
}t;

int main() {
	read(n); 
	t.insert(t.rt, -INF * 2 - 10, 0); t.insert(t.rt, INF + INF, 0);
	int ans = n;
	for(int i = 1, l, r; i <= n; ++i) {
		scanf("%d%d", &l, &r);
		int u = t.find(l), v = t.find(r), nxt = t.Nxt(v);
		if (u ^ v) {
			t.splay(u, 0); t.splay(nxt, u);
			t.val[t.ch[nxt][0]]++; t.tag[t.ch[nxt][0]]++;
		}
		if (nxt != 2) {t.del(nxt); --ans;}
		t.insert(t.rt, l, 0);
	}
	printf("%d\n", ans);
	return 0;	
}

标签:ch,int,Hitchhiking,pos,States,fa,tag,Baltic,dp
From: https://www.cnblogs.com/absolutey/p/16964521.html

相关文章

  • 记录一次实验室linux系统的GPU服务器死机故障的排查——Linux系统的Power States
    实验室的ubuntu服务器不知怎么的突然又崩溃了,死机重启,然后查看日志,发现了下面的情况:    由于从其他的日志中知道是显卡的问题引起的死机,而这个显卡的地址正好是D9:00,这......
  • Solution-P7650 [BalticOI 2007 Day 1] Ranklist Sorting(DP)
    容易发现一条性质:每个人最多只会被移动一次。说明人只有两种:移动的和不移动的。考虑枚举所有不移动的人,并最优化其它人的移动顺序。最开始第\(i\)个人的起点为\(i\),终......
  • Linux系统的Power States
    实验室的ubuntu服务器不知怎么的突然又崩溃了,死机重启,然后查看日志,发现了下面的情况:    由于从其他的日志中知道是显卡的问题引起的死机,而这个显卡的地址正好是D......
  • 洛谷 P6573 [BalticOI 2017] Toll 题解
    Link算是回归OI后第一道自己写的题(考CSP的时候可没回归)写篇题解纪念一下题目大意:\(n\)个点,\(m\)条单向边,每条边的两端点\(x\),\(y\)必定满足\(\left\lfloor\dfrac......
  • 开源状态机代码生成 StateSmith 支持C/C++
     StateSmithStateSmithisacrossplatform,free/opensourcetoolforgeneratingstatemachines.Thegeneratedcodeishumanreadable,haszerodependencies......
  • [BalticOI 2010] Mines 题解
    你谷linklojlink提供一种时间复杂度正确的高妙做法。首先题目有一条隐藏条件是保证\(n\not\equiv2\pmod3\)或\(m\not\equiv2\pmod3\),需要通过观察数据得到。我们......
  • [BalticOI2021Day2T1]The short shank
    [BalticOI2021Day2T1]Theshortshank真的会谢,就我是个傻逼去写长链剖分,直接成最慢的......