题解 玫瑰花精

传送门

此题高度恶心,极其卡细节,最后研究题解一个多小时才写对,值得什么时候再复做一下以自虐

这题貌似优先队列也可以做,
二元组维护空区间,再维护两个数组记录每个位置所对应的(如果有)向左和向右的两个二元组编号
开个bool数组作为失效标记就好了
先留坑,有空回来写

说下正解写法吧
\(l,r\)什么的一概初始化成0其实就可以
随时注意是左边的优于右边的,也就是说夹在左右区间中间的那部分其实优于右区间的部分(我大脑短路调了一下午重构了4次居然没发现这个问题)
还有需要特判区间1的\(l=0\)的情况,它所对应的貌似是在一个空区间内放花精
\(l-1, n-r, mid\)的比较实质上是对最左边花精左边,最右边花精右边,中间花精之间的比较,
所以要特判只有一个花精,没有中间这部分空间的情况

这题极适合练判边界什么的用,优先队列的思路有空也可以写写

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000100
#define ll long long 
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long 

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
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, m;

namespace force{
	int tab[N], a[N];
	bool vis[N];
	void solve() {
		for (int i=1,f,x; i<=m; ++i) {
			f=read(); x=read();
			if (f&1) {
				memset(a, 0, sizeof(int)*1010);
				a[0]=a[n+1]=INF;
				for (int i=1; i<=n; ++i) 
					if (vis[i]) a[i]=0;
					else a[i]=a[i-1]>n?a[i-1]-1:a[i-1]+1;
				for (int i=n,cnt=INF; i; --i) 
					if (vis[i]) cnt=0;
					else a[i]=min(a[i], a[i+1]+1);
				//cout<<"a: "; for (int i=1; i<=n; ++i) cout<<a[i]<<' '; cout<<endl;
				//cout<<"vis: "; for (int i=1; i<=n; ++i) cout<<vis[i]<<' '; cout<<endl;
				int maxn=0, maxi;
				for (int i=1; i<=n; ++i) if (!vis[i] && a[i]>maxn) maxn=a[i], maxi=i;
				vis[maxi]=1;
				tab[x]=maxi;
				printf("%d\n", maxi);
			}
			else vis[tab[x]]=0;
		}
	}
}

namespace task{
	const int SIZE=N<<2;
	int tab[1000010];
	int tl[SIZE], tr[SIZE], lran[SIZE], rran[SIZE], len[SIZE], pos[SIZE], cnt[SIZE];
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define l(p) lran[p]
	#define r(p) rran[p]
	#define len(p) len[p]
	#define pos(p) pos[p]
	#define cnt(p) cnt[p]
	void pushup(int p) {
		//cout<<"pushup "<<p<<' '<<tl(p)<<' '<<tr(p)<<endl;
		cnt(p)=cnt(p<<1)+cnt(p<<1|1);
		//cout<<"cnt: "<<cnt(p)<<endl;
		//l(p)=min(l(p<<1), l(p<<1|1));
		//r(p)=max(r(p<<1), r(p<<1|1));
		l(p)=l(p<<1)?l(p<<1):l(p<<1|1);
		r(p)=r(p<<1|1)?r(p<<1|1):r(p<<1);
		//if (cnt(p)<=1) {len(p)=pos(p)=0; return ;}
		if (len(p<<1)>=len(p<<1|1)) len(p)=len(p<<1), pos(p)=pos(p<<1);
		else len(p)=len(p<<1|1), pos(p)=pos(p<<1|1);
		if (l(p<<1|1)<=n && r(p<<1) && (l(p<<1|1)-r(p<<1))/2>=len(p<<1|1) && (l(p<<1|1)-r(p<<1))/2>len(p<<1)) len(p)=(l(p<<1|1)-r(p<<1))/2, pos(p)=(r(p<<1)+l(p<<1|1))>>1;
	}
	void build(int p, int l, int r) {
		//cout<<"build "<<p<<' '<<l<<' '<<r<<endl;
		tl(p)=l; tr(p)=r; l(p)=0; r(p)=0;
		//cout<<"len: "<<p<<' '<<len(p)<<endl;
		//cout<<"build-pos: "<<p<<' '<<pos(p)<<endl;
		if (l>=r) return ;
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
	}
	void upd(int p, int pos2) {
		//cout<<"upd "<<p<<' '<<pos2<<endl;
		if (!l(p)||pos2<l(p)) l(p)=pos2;
		if (!r(p)||pos2>r(p)) r(p)=pos2;
		if (tl(p)==tr(p)) {cnt(p)=1; l(p)=r(p)=tr(p); len(p)=0; pos(p)=0; return ;}
		int mid=(tl(p)+tr(p))>>1;
		if (pos2<=mid) upd(p<<1, pos2);
		else upd(p<<1|1, pos2);
		pushup(p);
	}
	int query() {
		if (!l(1)) {upd(1, 1); return 1;}
		//cout<<"query "<<l(1)<<' '<<r(1)<<' '<<len(1)<<' '<<pos(1)<<endl;
		int maxn, maxi;
		maxn = max(max(l(1)-1, n-r(1)), len(1));
		//cout<<"query cmp "<<l(1)-1<<' '<<n-r(1)<<' '<<len(1)<<endl;
		if (maxn==l(1)-1) {upd(1, 1); return 1;}
		else if (maxn==len(1)) {
			int ans=pos(1);
			//cout<<"ans: "<<pos(1)<<endl;
			upd(1, ans);
			return ans;
		}
		else {upd(1, n); return n;}
	}
	void remove(int p, int pos2) {
		assert(pos2);
		//cout<<"remove "<<p<<' '<<pos2<<endl;
		if (tl(p)==tr(p)) {l(p)=0; r(p)=0; len(p)=pos(p)=cnt(p)=0; return ;}
		int mid=(tl(p)+tr(p))>>1;
		if (pos2<=mid) remove(p<<1, pos2);
		else remove(p<<1|1, pos2);
		pushup(p);
	}
	void solve() {
		//memset(lran, 127, sizeof(lran));
		build(1, 1, n);
		for (int i=1,f,x; i<=m; ++i) {
			f=read(); x=read();
			if (f&1) printf("%d\n", tab[x]=query()); //, cout<<endl;
			else remove(1, tab[x]), tab[x]=0;
		}
	}
}

signed main()
{
	#ifdef DEBUG
	freopen("1.in", "r", stdin);
	#endif
	
	n=read(); m=read();
	task::solve();

	return 0;
}
posted @ 2021-07-25 21:34  Administrator-09  阅读(14)  评论(0编辑  收藏  举报