P8251 [NOI Online 2022 提高組] 丹釣戰
阿新 • • 發佈:2022-03-28
題面
有 \(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; }