题解 [NOI Online 2022 提高组] 丹钓战

传送门

读错题花了一点时间

发现可以扫描线,每次找最大的单调栈中的 \(t\) 满足 \(a_t\neq a_i\and b_t>b_i\),对区间 \([t+1, i]\) 产生 1 贡献
那么线段树可以做到 \(O(n\log n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 500010
#define fst first
#define snd second
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, q;
int a[N], b[N];
vector<pair<int, int>> que[N];

namespace force{
	int sta[N], top, ans;
	void solve() {
		for (int i=1,l,r; i<=q; ++i) {
			l=read(); r=read(); top=ans=0;
			for (int j=l; j<=r; ++j) {
				while (top && !(a[j]!=a[sta[top]]&&b[j]<b[sta[top]])) --top;
				if (!top) ++ans;
				sta[++top]=j;
			}
			printf("%d\n", ans);
		}
	}
}

namespace task1{
	int tem[N];
	int sta[N], ans[N], top;
	void solve() {
		for (int i=1,l,r; i<=q; ++i) {
			l=read(); r=read();
			que[r].pb({l, i});
		}
		for (int i=1; i<=n; ++i) {
			// cout<<"i: "<<i<<endl;
			int pos=0;
			for (int j=1; j<=top; ++j) if (a[sta[j]]!=a[i] && b[sta[j]]>b[i]) pos=sta[j];
			// cout<<"pos: "<<pos<<endl;
			for (int j=pos+1; j<=i; ++j) ++tem[j];
			for (auto it:que[i]) ans[it.snd]=tem[it.fst];
			while (top && !(a[i]!=a[sta[top]]&&b[i]<b[sta[top]])) --top;
			sta[++top]=i;
		}
		for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
	}
}

namespace task2{
	int sta[N], bit[N], ans[N], top;
	int tl[N<<2], tr[N<<2];
	pair<int, int> fir[N<<2], sec[N<<2];
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define fir(p) fir[p]
	#define sec(p) sec[p]
	inline void upd(int i, int dat) {for (; i<=n; i+=i&-i) bit[i]+=dat;}
	inline int query(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit[i]; return ans;}
	inline void pushup(int p) {
		fir(p)=fir(p<<1).fst>fir(p<<1|1).fst?fir(p<<1):fir(p<<1|1);
		sec(p)={0, 0};
		if (fir(p<<1).snd!=fir(p).snd && fir(p<<1).fst>sec(p).fst) sec(p)=fir(p<<1);
		if (fir(p<<1|1).snd!=fir(p).snd && fir(p<<1|1).fst>sec(p).fst) sec(p)=fir(p<<1|1);
		if (sec(p<<1).snd!=fir(p).snd && sec(p<<1).fst>sec(p).fst) sec(p)=sec(p<<1);
		if (sec(p<<1|1).snd!=fir(p).snd && sec(p<<1|1).fst>sec(p).fst) sec(p)=sec(p<<1|1);
	}
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r;
		if (l==r) return ;
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
		pushup(p);
	}
	void upd(int p, int pos, pair<int, int> val) {
		if (tl(p)==tr(p)) {fir(p)=val; return ;}
		int mid=(tl(p)+tr(p))>>1;
		if (pos<=mid) upd(p<<1, pos, val);
		else upd(p<<1|1, pos, val);
		pushup(p);
	}
	int findmx(int p, int ban, int k) {
		if (tl(p)==tr(p)) return (fir(p).fst>k&&fir(p).snd!=ban)?tl(p):0;
		int maxr=0;
		if (fir(p<<1|1).snd!=ban) maxr=max(maxr, fir(p<<1|1).fst);
		if (sec(p<<1|1).snd!=ban) maxr=max(maxr, sec(p<<1|1).fst);
		if (maxr>k) return findmx(p<<1|1, ban, k);
		else return findmx(p<<1, ban, k);
	}
	void solve() {
		// cout<<double(sizeof(tl)*2+sizeof(fir)*2)/1000/1000<<endl; exit(0);
		for (int i=1,l,r; i<=q; ++i) {
			l=read(); r=read();
			que[r].pb({l, i});
		}
		build(1, 1, n);
		for (int i=1; i<=n; ++i) {
			// cout<<"i: "<<i<<endl;
			int pos=findmx(1, a[i], b[i]);
			// for (int j=1; j<=top; ++j) if (a[sta[j]]!=a[i] && b[sta[j]]>b[i]) pos=sta[j];
			// cout<<"pos: "<<pos<<endl;
			// for (int j=pos+1; j<=i; ++j) ++tem[j];
			upd(pos+1, 1); upd(i+1, -1);
			for (auto it:que[i]) ans[it.snd]=query(it.fst);
			while (top && !(a[i]!=a[sta[top]]&&b[i]<b[sta[top]])) upd(1, sta[top--], {0, 0});
			sta[++top]=i; upd(1, sta[top], {b[i], a[i]});
		}
		for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
	}
}

signed main()
{
	freopen("stack.in", "r", stdin);
	freopen("stack.out", "w", stdout);

	n=read(); q=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	for (int i=1; i<=n; ++i) b[i]=read();
	// force::solve();
	// task1::solve();
	task2::solve();

	return 0;
}
posted @ 2022-03-26 14:16  Administrator-09  阅读(3)  评论(0编辑  收藏  举报