51nod 1302 矩形面积交 (不要把题目玩工业了。。)
来源:互联网 发布:mac双系统移除win8后 编辑:程序博客网 时间:2024/05/16 20:57
Description
有2N个矩形,这些矩形被标号为0 ~ 2N-1,对于第i个矩形其长宽分别为X[i]与Y[i]。现在要把这2N个矩形分为两组,每组N个,每个矩形恰好分到两组中的一组里。分成两组后,设两组分别为A组、B组,对于每一组矩形,你需要分别完成如下任务:将该组中的N个矩形依次放在一个平面上,可以相互重叠,要求每个矩形的4条边都平行于平面坐标系的X轴或Y轴,矩形在摆放时可以旋转90度后再摆放。N个矩形摆放完后,使这N个矩形共同重叠的面积最大;设A组的最大面积为SA,B组的最大面积为SB。请寻找一种恰当的分组方法,使SA+SB最大,并输出SA+SB的这个极值。
Solution
考虑统一将短边作为x,长边作为y,按x排序后,一定会取第一个矩形的x作为一组矩形的最小x,再枚举另一个矩形的x作为另一组中最小的x然后贪心即可。
考试的时候脑子很不清醒,用了个std::set
,怒刚了两个多小时正解没刚出来(我真是太菜了)。考完后继续改题,改对后发现TLE掉了。。。然后我灵机一动(脑子发抽),咦?区间第k小不就是主席树吗?!于是开始怒刚主席树,刚到晚上一直TLE+WA,后来XIO大佬来帮忙,发现竟是数组开小了(原题中输入n表示有2n个矩形),XIO大佬真是太强啦!!终于A掉了,回顾一下代码,呃?为什么要用主席树??这里不要求可持久化啊,求第k小直接线段树就行了啊。。。
其实题解是优先队列维护。。老K的std写的是splay。。。有人比我更工业?
总结:借用何爷爷暑假集训时的话,数据结构永远只是个工具,不要把题目玩工业了。面对不同的题目,不要生搬硬套,要机智灵活地使用数据结构,才能更节约时间,减少代码量、复杂度。
Code
发一波被玩工业的代码吧。。(其实主席树并不长,,,)
#include<bits/stdc++.h>using namespace std;#define For(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i)#define Fordown(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i)#define Set(a , b) memset(a , b , sizeof(a))#define pb(a) push_back(a)#define mp(a, b) make_pair(a, b)#define ALL(a) (a).begin(), (a).end()#define SZ(a) ((int)(a).size())#define mid ((l + r) >> 1)#define INF (0x3f3f3f3f)#define INF1 (2139062143)#define Mod (1000000007)typedef long long LL;template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; }int _ , __;char c_;inline int read(){ for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __;}inline void File(){#ifdef hany01 freopen("square.in" , "r" , stdin); freopen("square.out" , "w" , stdout);#endif}const int maxn = 200060;struct Matrix{ int x, y; bool operator < (const Matrix &matrix) const { return x < matrix.x || (x == matrix.x && y < matrix.y); }}M[maxn << 1];struct President_Tree{ int v, lc, rc;}tr[maxn * 30];LL Ans;int n, log2n[maxn << 1], Min[maxn << 1][18], ls[maxn << 1], len, rt[maxn], cnt;inline void checkmin(int &min1, int &min2, int num) { if (min1 > num) { min2 = min1; min1 = num; } else if (min2 > num) min2 = num; }int update(int last, int l, int r, int x){ int now = ++ cnt; tr[now] = tr[last]; ++ tr[now].v; if (l < r) { if (x <= mid) tr[now].lc = update(tr[last].lc, l, mid, x); else tr[now].rc = update(tr[last].rc, mid + 1, r, x); } return now;}inline void Init(){ n = read(); For(i, 1, (n << 1)) { M[i].x = read(), M[i].y = read(); if (M[i].x > M[i].y) swap(M[i].x, M[i].y); ls[i] = M[i].y; } sort(M + 1, M + 1 + (n << 1)); sort(ls + 1, ls + 1 + (n << 1)); len = unique(ls + 1, ls + 1 + (n << 1)) - ls - 1; For(i, 1, n << 1) rt[i] = update(rt[i - 1], 1, len, lower_bound(ls + 1, ls + 1 + len, M[i].y) - ls); log2n[1] = 0; For(i, 2, n << 1) log2n[i] = log2n[i >> 1] + 1; For(i, 1, n << 1) Min[i][0] = M[i].y; For(j, 1, log2n[n << 1]) for (int i = 1; i + (1 << j) - 1 <= (n << 1); ++ i) Min[i][j] = min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]);}inline int query_st(int l, int r) { return min(Min[l][log2n[r - l + 1]], Min[r - (1 << log2n[r - l + 1]) + 1][log2n[r - l + 1]]); }inline LL Max(LL a, LL b) { return a > b ? a : b; }int query(int rt1, int rt2, int l, int r, int k){ if (tr[rt2].v - tr[rt1].v < k) return 0; if (l == r) return l; int num = tr[tr[rt2].lc].v - tr[tr[rt1].lc].v; if (num >= k) return query(tr[rt1].lc, tr[rt2].lc, l, mid, k); else return query(tr[rt1].rc, tr[rt2].rc, mid + 1, r, k - num);}inline void Solve(){ ls[0] = INF; int x1, x2; LL y1 = INF, y2 = INF; x1 = 1; For(i, n + 2, n * 2) chkmin(y2, (LL)M[i].y); for (x2 = n + 1; x2 >= 2; -- x2) { y1 = query_st(x1, x2 - 1); if (x2 == n + 1) { chkmax(Ans, M[x1].x * y1 + M[x2].x * min(y2, (LL)M[x2].y)); chkmin(y2, (LL)M[x2].y); continue; } if (y2 >= y1) { chkmax(Ans, M[x1].x * y1 + (LL)M[x2].x * min(ls[query(rt[x2], rt[n << 1], 1, len, n - x2 + 2)], M[x2].y)); } else { chkmax(Ans, M[x1].x * y2 + (LL)M[x2].x * min((LL)ls[query(rt[x2], rt[n << 1], 1, len, n - x2 + 2)], (LL)M[x2].y)); chkmax(Ans, M[x2].x * min((LL)M[x2].y, y2) + M[x1].x * (LL)min(y1, (LL)(ls[query(rt[x2], rt[n << 1], 1, len, n)]))); } chkmin(y2, (LL)M[x2].y); } printf("%lld\n", Ans); cerr << Ans << endl;}int main(){ File(); Init(); Solve(); return 0;}//楚江微雨里,建业暮钟时。//漠漠帆来重,冥冥鸟去迟。//海门深不见,浦树远含滋。//相送情无限,沾襟比散丝。//--韦应物《赋得暮雨送李胄》
- 51nod 1302 矩形面积交 (不要把题目玩工业了。。)
- 【51nod】1302 矩形面积交【优先队列贪心】
- 矩形面积交
- 11.矩形面积交
- 矩形面积交---蓝桥杯
- 矩形面积交
- 矩形面积交
- 矩形面积交
- 矩形面积交
- 蓝桥杯 矩形面积交
- 矩形面积交
- 矩形面积交
- 矩形面积交
- 判断矩形面积交
- 1609:矩形面积交
- 蓝桥杯:矩形面积交
- 蓝桥杯 矩形面积交
- 51nod 1102 面积最大的矩形
- Linux中执行shell脚本的4种方法总结
- 2017.11.7测试
- is 和 == 区别
- vim常用快捷键
- Unity3d入门基础之UGUI-基本控件的学习
- 51nod 1302 矩形面积交 (不要把题目玩工业了。。)
- ClassLoader的原理和应用
- OkHttp get请求 和post请求
- Ubuntu 16.04 LTS 安装RealSense R200 驱动以及SDK配置+QT+OpenCV
- 玩转SpringBoot
- 剑指offer------回溯法
- 11月的雨
- 1025. 反转链表 (25)
- 1用switch语句从控制台输入100以内的分数判断优秀,良好,及格不及格属于哪一个区间