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;}//楚江微雨里,建业暮钟时。//漠漠帆来重,冥冥鸟去迟。//海门深不见,浦树远含滋。//相送情无限,沾襟比散丝。//--韦应物《赋得暮雨送李胄》
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 黄金棒打不开怎么办 枪火游侠黑屏怎么办 老虎直播封了怎么办 网卡及驱动异常怎么办 电脑刺激战场卡怎么办 grub 文件兼容性错误怎么办 电脑程序不兼容怎么办 运行程序不兼容怎么办 usb驱动删了怎么办 电脑卡死 点不开怎么办 电脑开机找不到驱动程序怎么办 显卡关了黑屏怎么办 xp全部程序打不开怎么办 七彩凤电脑打不开怎么办 鹦鹉鱼不敢吃食怎么办 甘油三酯1.87怎么办 手机移动数据网打不开怎么办 苹果手机浏览器打不开没网怎么办 玩多人游戏很紧张怎么办 dnf容易掉线怎么办 qq名字改不了怎么办 手被打火机烧伤怎么办 无效的菜单句柄怎么办 网课被发现刷课怎么办 华硕笔记本玩游戏卡怎么办 手机玩游戏卡顿怎么办? 360n4s玩游戏卡怎么办 手机玩游戏卡死怎么办 游戏占用cpu过高怎么办 h1z1 cpu占用高怎么办 电视盒子网速慢怎么办 gta5解压完然后怎么办 火山遭举报了怎么办 火山被恶意举报怎么办 gta5无网络链接怎么办 pdf格式没有解压密码怎么办 电脑感染蠕虫病毒怎么办 手机积分被盗兑怎么办 自动雨伞卡住了怎么办 全自动伞收不了怎么办 雨伞收不起来怎么办