积木「CSP-S全国排位赛第一场」

题意

搜狗截图20191102120007.png


思路

首先有一点是肯定的,掉落的形状会像一个三角形一样。(因为总体的排列像砖墙一样,所以掉落范围只能缩小不能扩大)

于是我们可以维护初始的所有区间,然后在向上转移的过程中合并区间、统计答案。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

	template<typename T>inline void read (T &x) {
		x=0;T f=1;char c=getchar();
		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
		x*=f;
	}

	template<typename T>inline void write (T x) {
		if (x<0) putchar('-'),x*=-1;
		if (x>=10) write(x/10);
		putchar(x%10+'0');
	}

}

using namespace StandardIO;

namespace Project {
	#define int long long

	const int N=300300;
	
	int n,ans;
	pair<int,int> p[N];
	int tot;
	struct node {
		int x,l,r;
		node () {}
		node (int _x,int _l,int _r) : x(_x),l(_l),r(_r) {}
	} line[N];
	
	inline bool cmp (const pair<int,int> x,const pair<int,int> y) {
		return x.first<y.first;
	}
	inline bool cmp2 (const node x,const node y) {
		return (x.l!=y.l)?(x.l<y.l):(x.r<y.r);
	}
	inline void merge () {
		int cnt=1;
		sort(line+1,line+tot+1,cmp2);
		for (register int i=2; i<=tot; ++i) {
			if (line[i].l<=line[cnt].r+1) line[cnt].r=max(line[cnt].r,line[i].r);
			else line[++cnt]=line[i];
		}
		tot=cnt;
	}
	inline void update () {
		int cnt=0;
		for (register int i=1; i<=tot; ++i) {
			++line[i].l,--line[i].r;
			if (line[i].l<=line[i].r) line[++cnt]=line[i];
		}
		tot=cnt;
	}
	
	inline void MAIN () {
		read(n);
		for (register int i=1; i<=n; ++i) 
			read(p[i].first),read(p[i].second);
		sort(p+1,p+n+1,cmp);
		int cur=1,top=0;
		while (1) {
			if (!tot) {
				if (cur>n) break;
				top=p[cur].first;
			}
			while (cur<=n&&p[cur].first==top) line[++tot]=node(p[cur].first,p[cur].second,p[cur].second+1),++cur;
			merge();
			for (register int i=1; i<=tot; ++i) {
				ans+=(line[i].r-line[i].l+1)>>1;
			}
			update();
			++top;
		}
		write(ans);
	}
	
	#undef int
}

int main () {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	Project::MAIN();
}

原文地址:https://www.cnblogs.com/ilverene/p/11781320.html