【CF 793G】Oleg and Chess

这篇博客讨论了在有删除矩形限制的n×n棋盘上放置棋子的问题,要求每行每列至多一个棋子。通过分析,提出了使用线段树优化网络流建图的方法,并引入扫描线策略减少无效切割,将复杂度控制在可接受范围内。虽然代码实现较为复杂,但该策略提供了一种解决此类问题的思路。
摘要由CSDN通过智能技术生成

##题面
链接_洛谷
链接_CF
简述一下题意:
在一个 n ∗ n ( n ≤ 10000 ) n*n(n\leq10000) nn(n10000)的棋盘上放棋子,要求一行一列不能放两个棋子。现在删去 n n n个矩形,输入方式是给左下坐标和右上坐标。删去的矩形不能放棋子,但棋子隔着一个删去的矩形仍然会互相干扰。求最多放几个棋子。

##分析
首先考虑放棋子是什么意思(这是一个挺常见的转化),一行和一列去配对,每一行每一列只能配对一次。删去的部分就是这些行和这些列不可以配对。
连10000*10000条边显然要超时炸空间,那么我们考虑线段树优化建图。不了解优化建图的建议出门百度网络流优化建图。但是这个时候遇到一个问题,就是优化建图是一段区间向一段区间连边,但是我们只知道一段区间不能和一段区间连边。所以考虑如何把剩余部分划分成若干矩形。
一种十分容易想到的方式是直接从所有删掉的矩形的边那里切开(如图,红色是删掉的部分),然而如果删掉的是一条对角线上的所有矩形这就变暴力了TAT。
画图画的,轻喷qwq
我们观察一下这个切分方式:我们切分了很多无用的线,对于在它上面很多的矩形切下来的线,完全可以置之不理。
于是我们考虑扫描线。具体步骤如下:对于每一个矩形的下边,它以下部分切一个矩形出来。对于一个矩形的上边,左右两侧切两个矩形出来。如图。
这里写图片描述
现在来考察复杂度:对于每个矩形,遇到底边的时候出现一个矩形,顶边的时候出现两个矩形,于是我们一共会剖分 O ( n ) O(n) O(n)个矩形,可以接受。
细节有点麻烦,以后有功夫了上来写一下

代码

十分晦涩qwq
因为自己改了好多遍,拍出了无数错和没考虑好的地方所以就十分丑陋
以后也许会来补一补注释什么的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <math.h>
#include <set>
#include <ctime>
#define MAXN 10050
#define INF (1<<28)
#define LLINF (1LL<<40)
#define LL long long
#define ri register int
using namespace std;
int n, Q, maxx, cnt, ecnt, tot, S, T;
int q[MAXN<<6], level[MAXN<<3], Cnt[2], interval[2][MAXN], ppos[MAXN];
/*The first line contains single integer n  ( 1<=n<=10000 ) — the size of the board.
The second line contains single integer q  ( 0<=q<=10000  ) — the number of deleted rectangles.
The next q lines contain the information about the deleted rectangles.
Each of these lines contains four integers x1 y1, x2 y2;
the coordinates of the lower left and the upper right cells of a deleted rectangle.*/ 
struct Node {
   
    int l, r, h, ty, hh;
    bool operator < (const Node &x) const {
   
        if(h == x.h && ty == x.ty) return r < x.r;
        if(h == x.h) return ty > x.ty;
        return h < x.h;
    }
}line[MAXN*3];
struct NODE {
   
    int pos, lhh, rhh, high;
    bool operator < (const NODE &x) const {
   
        return pos < x.pos;
    }
};
struct node {
   
    int v, c; node *next, *rev;
}pool[MAXN*1000], *h[MAXN<<5], *cur[MAXN<<5];
set <NODE> s;
inline void addedge(int u, int v, int c) {
   
    node *p = &pool[ecnt++], *q = &pool[ecnt++];
    *p = node{
   v, c
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值