题意:给你T个例子,然后给出N,M,Q(2e9,2e9,1e5),即给出了一个(0,0)到(N,M)的矩形
现在有Q次询问,0 a 表示在x轴的a处画一条平行于y轴的分割线。1 a 表示在y轴的a处画一条平行于x轴的平行线
问每一次分割后最大的矩形面积为多少。
思路:一开始拿到这道题我想到了线段树,然而...怎么更新边长(单点更新割点然后来维护区间最长段?)(当然用线段树是肯定能做的)
看了网上题解之后 基本上都是使用的set 以及 multiset来做(因为2s多)。这里就当熟悉set的操作换一种来做吧。
multiset可以保留多个重复的边,同时还自带二分排序。 multiset.erase(multiset.find(a)); 可以只消除集合中一个a,multiset.erase(a);则会删除集合中所有a.
code:
#include<iostream> #include<cstring> #include<cstdio> #include<set> #include<algorithm> #define ll long long using namespace std; const int maxn = 20000 + 10; set<ll> x, y;//分割点用set存储 multiset<ll> lenx, leny;//边长用mulity来存储 int main(){ int T; ll n, m, q; scanf("%d", &T); while(T--){ scanf("%lld%lld%lld", &n, &m, &q); x.clear(),y.clear(); lenx.clear(),leny.clear(); x.insert(0),x.insert(n),lenx.insert(n); y.insert(0),y.insert(m),leny.insert(m); set<ll>::iterator it; while(q--){ ll p; int op; scanf("%d%lld", &op, &p); if(op == 0 && x.count(p) == 0){ //如果切线p不存在,找到比p大的第一个位置,插入这个位置的左边 it = x.lower_bound(p); //加入新分割出的右边的边 lenx.insert(*it - p); //将长为len的消掉(对应的边) int len = *it - *(--it); lenx.erase(lenx.find(len)); //插入左边的边 lenx.insert(p - *it); x.insert(p); } else if(op == 1 && y.count(p) == 0){ it = y.lower_bound(p); leny.insert(*it - p); int len = *it - *(--it); leny.erase(leny.find(len)); leny.insert(p - *it); y.insert(p); } it = lenx.end(); ll ansx = *(--it); it = leny.end(); ll ansy = *(--it); printf("%lld ", ansx * ansy); } } return 0; }