1. 程式人生 > 其它 >P8251 [NOI Online 2022 提高組] 丹釣戰

P8251 [NOI Online 2022 提高組] 丹釣戰

題面

\(n\) 個二元組 \((a_i, b_i)\),編號為 \(1\)\(n\)

有一個初始為空的棧 \(S\),向其中加入元素 \((a_i, b_i)\) 時,先不斷彈出棧頂元素直至棧空或棧頂元素 \((a_j , b_j)\) 滿足 \(a_i \neq a_j\)\(b_i < b_j\),然後再將其加入棧中。

如果一個二元組入棧後棧內只有這一個元素,則稱該二元組是“成功的”。

\(q\) 個詢問 \([l_i, r_i]\),表示若將編號在 \([l_i, r_i]\) 中的二元組按編號從小到大依次入棧,會有多少個二元組是“成功的”。

詢問之間相互獨立

思路

既然是丹(單)釣(調)戰(棧),所以肯定是可以單調棧的。

首先用單調棧預處理,用連結串列的思想來維護出棧的元素。如果沒有後繼,那麼就設為 \(n+1\)

然後對於每一個詢問,只要維護 \(l\)\(r\) 的連結串列元素計數就好了。

非正解但是民間資料+卡常可過。

程式碼

#include <bits/stdc++.h>
#define LIWENX_AK_IOI for(int i=1;i<=n;i++)
#define OLLO_AK_IOI while(m--)
using namespace std;

namespace IO {
	const int SIZE=1<<21;
	static char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=oS+SIZE-1;
	int qr;
	char qu[55],c;
	bool f;
#define getchar() (IO::iS==IO::iT?(IO::iT=(IO::iS=IO::ibuf)+fread(IO::ibuf,1,IO::SIZE,stdin),(IO::iS==IO::iT?EOF:*IO::iS++)):*IO::iS++)
#define putchar(x) *IO::oS++=x,IO::oS==IO::oT?flush():0
#define flush() fwrite(IO::obuf,1,IO::oS-IO::obuf,stdout),IO::oS=IO::obuf
#define puts(x) IO::Puts(x)
	template<typename T>
	inline void read(T&x) {
		for(f=1,c=getchar(); c<48||c>57; c=getchar())f^=c=='-';
		for(x=0; c<=57&&c>=48; c=getchar()) x=(x<<1)+(x<<3)+(c&15);
		x=f?x:-x;
	}
	template<typename T>
	inline void write(T x) {
		if(!x) putchar(48);
		if(x<0) putchar('-'),x=-x;
		while(x) qu[++qr]=x%10^48,x/=10;
		while(qr) putchar(qu[qr--]);
	}
	inline void Puts(const char*s) {
		for(int i=0; s[i]; i++)
			putchar(s[i]);
		putchar('\n');
	}
	struct Flusher_ {
		~Flusher_() {
			flush();
		}
	} io_flusher_;
}
using IO::read;
using IO::write;


const int SIZE = 5E5+1;
int n,m;
int a[SIZE],b[SIZE];

int top=0;
int sta[SIZE],linkable[SIZE];

inline void yuchuli(int i) {
	while(top!=0&&((a[sta[top]]==a[i]||b[sta[top]]<=b[i]))) {
		linkable[sta[top]]=i;
		top--; // Pop
	}
	sta[++top]=i; // Push
}

inline void yuchuli2(int i) {
	if(!linkable[i]) {
		linkable[i]=n+1;
	}
}

int main() {
	read(n);
	read(m);
	LIWENX_AK_IOI {
		read(a[i]);
	}
	LIWENX_AK_IOI {
		read(b[i]);
	}
	LIWENX_AK_IOI {
		yuchuli(i);
	}
	LIWENX_AK_IOI {
		yuchuli2(i);
	}
	OLLO_AK_IOI {
		int l,r,i,ans=0;
		read(l);
		read(r);
		i=l;
		while(i<=r) {
			ans++;
			i=linkable[i];
		}
		write(ans);
		putchar('\n');
	}
	return 0;
}