NOICA 数据结构专题

怎么啥也不会???

A. [TJOI2016] 排序

好像是典中典题,在别人博客里见过 114514 次,当然,我不会

首先思考排序有没有好的处理方式

好像想不到

但是这个单次询问比较蹊跷

算了,看了题解,发现可以使用 【模板】线段树分裂 硬艹过去

进行了一个学习(学了一上午,我是智障)

君子报仇,一上午不晚

考虑给每个点开一棵动态开点线段树,用一个 set 维护连续段的 l 、r 。排序的过程其实就是暴力线段树合并,如果说排序区间在一个有序段内,那就暴力线段树分裂,查询就是直接对于某一棵树做一个第 k 小或第 k 大

爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽爽

好吧,没这么爽,因为这玩意太 * * 难写了,还是写离线做法吧

有一个妙妙思路,就是考虑序列二值化,变成判定问题,排序就是你对一堆0/1排序,当前位置为1则合法。

做完了。

代码比较好写

B. 省选联考2020 森林冰火人

这东西本质不难,发现冰、火越接近答案越大,手算一下柿子,直接树状数组二分就做完了

又几把调了一下午。。。

C. Good Pairs

肯定是对 r 扫描线然后数据结构维护 l

好像可以维护值域,每次贪心扩展,答案是扩展到的点的个数

算合法的 l 容易算重,考虑正难则反统计不合法的

然后不会了,看了一眼题解

有一个观察,若 $ (l,r) $ 合法,则一定可以构造出来两点间单调不升或单调不降的路径,

那不就做完了????(紧接着口胡失败了)

结果翻了一下发现了相同的思路,我是小乐乐

分别考虑上升或下降

\(f_i\) 和 \(g_i\) 分别表示 以 i 为右端点的 不合法的 上升/下降 对的数量

转移:找到最近的 $ v-k \leq Δ \leq v $ 或 $ v \leq Δ \leq v+k $ 的位置,分别转移

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e5+5;
const int V=100000;
int T,n,k;
int tot=0;
int t[N*20],ls[N*20],rs[N*20],mx[N*20];
int rt[N],a[N],f[N],g[N];
void build(int l,int r,int &idx)
{
	if(!idx) idx=++tot;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(l,mid,ls[idx]);
	build(mid+1,r,rs[idx]);
}
void ins(int lst,int &idx,int l,int r,int pos,int val)
{
	idx=++tot;
	t[idx]=t[lst]+1;mx[idx]=max(mx[lst],val);
	if(l==r) return;
	ls[idx]=ls[lst];rs[idx]=rs[lst];
	int mid=(l+r)>>1;
	if(pos<=mid) ins(ls[lst],ls[idx],l,mid,pos,val);
	else ins(rs[lst],rs[idx],mid+1,r,pos,val);
}
int qmx(int idx,int l,int r,int ql,int qr)
{
	if(!idx) return 0;
	if(ql>qr) return 0;
	if(ql<=l&&r<=qr) return mx[idx];
	int mid=(l+r)>>1;
	int mx=0;
	if(ql<=mid) mx=qmx(ls[idx],l,mid,ql,qr);
	if(mid<qr) mx=max(mx,qmx(rs[idx],mid+1,r,ql,qr));
	return mx;
}
int qsm(int idx,int l,int r,int ql,int qr)
{
	if(!idx) return 0;
	if(ql>qr) return 0;
	if(ql<=l&&r<=qr) return t[idx];
	int mid=(l+r)>>1;
	int sm=0;
	if(ql<=mid) sm+=qsm(ls[idx],l,mid,ql,qr);
	if(mid<qr) sm+=qsm(rs[idx],mid+1,r,ql,qr);
	return sm;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>T;
	build(1,V,rt[0]);
	while(T--)
	{
		cin>>n>>k;
		for(int i=1;i<=n;i++) cin>>a[i];
		ll ans=0;tot=2*V;
		for(int i=1;i<=n;i++)
		{
			int x=qmx(rt[i-1],1,V,a[i]-k,a[i]);
			f[i]=f[x]+qsm(rt[i-1],1,V,1,a[i]-k-1)-qsm(rt[x],1,V,1,a[i]-k-1);
			int y=qmx(rt[i-1],1,V,a[i],a[i]+k);
			g[i]=g[y]+qsm(rt[i-1],1,V,a[i]+k+1,V)-qsm(rt[y],1,V,a[i]+k+1,V);
			
			ans+=i-f[i]-g[i];
			ins(rt[i-1],rt[i],1,V,a[i],i);
		}
		cout<<ans<<'\n';
	}
	return 0;
}

D. Red Sequence

第一眼感觉很典,直接化一化式子就成了 cdq 板子

令 \(f_i\) 表示前 i 个位置的答案,令 $ x $ 和 $ y $ 表示红减黄和红减蓝的前缀和

若满足

\[\begin{cases} j<i\\ x_j \leq x_i\\ y_j \leq y_i\\ \end{cases} \]

则有转移 $ f_i=\max(f_j+i-j,f_{i-1}) $,直接上 cdq 做到 \(\log^2\)

一看数据范围 $ n \leq 10^6 $,傻了

依旧看题解环节

考虑只保留有用的状态

首先,前一个位置是有用的,特判

其次,有可能可以取满整个前缀,特判

最后,不难发现可以贪心 "取临界" ,即只考虑 $ x_i = x_j $ 或 $ y_i = y_j $ ,对每个 $ x_i $ 、 $ y_i $ 分别开一颗动态开点线段树,转移即可

所有情况取 max

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int V=1e6;
int n;
int x[V+5],y[V+5],f[V+5];
int rt[2][V*2+2];
int mx[V*50],ls[V*50],rs[V*50];
int tot=0;
void ins(int &idx,int l,int r,int pos,int val)
{
	if(!idx) idx=++tot,mx[idx]=-V;
	mx[idx]=max(mx[idx],val);
	if(l==r) return;
	int mid=(l+r)>>1;
	if(pos<=mid) ins(ls[idx],l,mid,pos,val);
	if(mid<pos) ins(rs[idx],mid+1,r,pos,val);
}
int query(int idx,int l,int r,int ql,int qr)
{
	if(!idx) return -V;
	if(ql<=l&&r<=qr) return mx[idx];
	int mid=(l+r)>>1;
	int res=-V;
	if(ql<=mid) res=query(ls[idx],l,mid,ql,qr);
	if(mid<qr) res=max(res,query(rs[idx],mid+1,r,ql,qr));
	return res; 
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int r,yl,b;
		cin>>r>>yl>>b;
		x[i]=x[i-1]+r-yl;
		y[i]=y[i-1]+r-b;
	}
	for(int i=1;i<=n;i++)
	{
		if(x[i]>=0&&y[i]>=0) f[i]=i;
		else
		{
			f[i]=max(query(rt[0][x[i]+V],-V,V,-V,y[i]),query(rt[1][y[i]+V],-V,V,-V,x[i]))+i;
			f[i]=max(f[i],f[i-1]); 
		}
		ins(rt[0][x[i]+V],-V,V,y[i],f[i]-i);
		ins(rt[1][y[i]+V],-V,V,x[i],f[i]-i);
	}
	cout<<f[n]<<'\n';
	return 0;
}

E.[Ynoi Easy Round 2014] 不归之人与望眼欲穿的人们

首先数据范围 $ n\leq 5 \times 10^4 $ 启示大数据结构 (废话)

posted @ 2026-11-09 09:12  IAKPSC  阅读(3)  评论(0)    收藏  举报